- Move StgIsStorageFile16's implementation to StgIsStorageFile; port
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include "winerror.h"
29 #include "winnls.h"
30 #include "wine/unicode.h"
31 #include "font.h"
32 #include "wine/debug.h"
33 #include "gdi.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(font);
36 WINE_DECLARE_DEBUG_CHANNEL(gdi);
37
38 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
39 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
40 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
41 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
42 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
43
44 static const struct gdi_obj_funcs font_funcs =
45 {
46     FONT_SelectObject,  /* pSelectObject */
47     FONT_GetObject16,   /* pGetObject16 */
48     FONT_GetObjectA,    /* pGetObjectA */
49     FONT_GetObjectW,    /* pGetObjectW */
50     NULL,               /* pUnrealizeObject */
51     FONT_DeleteObject   /* pDeleteObject */
52 };
53
54 #define ENUM_UNICODE    0x00000001
55 #define ENUM_CALLED     0x00000002
56
57 typedef struct
58 {
59     GDIOBJHDR   header;
60     LOGFONTW    logfont;
61 } FONTOBJ;
62
63 typedef struct
64 {
65   LPLOGFONT16           lpLogFontParam;
66   FONTENUMPROC16        lpEnumFunc;
67   LPARAM                lpData;
68
69   LPNEWTEXTMETRICEX16   lpTextMetric;
70   LPENUMLOGFONTEX16     lpLogFont;
71   SEGPTR                segTextMetric;
72   SEGPTR                segLogFont;
73   HDC                   hdc;
74   DC                   *dc;
75   PHYSDEV               physDev;
76 } fontEnum16;
77
78 typedef struct
79 {
80   LPLOGFONTW          lpLogFontParam;
81   FONTENUMPROCW       lpEnumFunc;
82   LPARAM              lpData;
83   DWORD               dwFlags;
84   HDC                 hdc;
85   DC                 *dc;
86   PHYSDEV             physDev;
87 } fontEnum32;
88
89 /*
90  *  For TranslateCharsetInfo
91  */
92 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
93 #define MAXTCIINDEX 32
94 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
95   /* ANSI */
96   { ANSI_CHARSET, 1252, FS(0)},
97   { EASTEUROPE_CHARSET, 1250, FS(1)},
98   { RUSSIAN_CHARSET, 1251, FS(2)},
99   { GREEK_CHARSET, 1253, FS(3)},
100   { TURKISH_CHARSET, 1254, FS(4)},
101   { HEBREW_CHARSET, 1255, FS(5)},
102   { ARABIC_CHARSET, 1256, FS(6)},
103   { BALTIC_CHARSET, 1257, FS(7)},
104   { VIETNAMESE_CHARSET, 1258, FS(8)},
105   /* reserved by ANSI */
106   { DEFAULT_CHARSET, 0, FS(0)},
107   { DEFAULT_CHARSET, 0, FS(0)},
108   { DEFAULT_CHARSET, 0, FS(0)},
109   { DEFAULT_CHARSET, 0, FS(0)},
110   { DEFAULT_CHARSET, 0, FS(0)},
111   { DEFAULT_CHARSET, 0, FS(0)},
112   { DEFAULT_CHARSET, 0, FS(0)},
113   /* ANSI and OEM */
114   { THAI_CHARSET,  874,  FS(16)},
115   { SHIFTJIS_CHARSET, 932, FS(17)},
116   { GB2312_CHARSET, 936, FS(18)},
117   { HANGEUL_CHARSET, 949, FS(19)},
118   { CHINESEBIG5_CHARSET, 950, FS(20)},
119   { JOHAB_CHARSET, 1361, FS(21)},
120   /* reserved for alternate ANSI and OEM */
121   { DEFAULT_CHARSET, 0, FS(0)},
122   { DEFAULT_CHARSET, 0, FS(0)},
123   { DEFAULT_CHARSET, 0, FS(0)},
124   { DEFAULT_CHARSET, 0, FS(0)},
125   { DEFAULT_CHARSET, 0, FS(0)},
126   { DEFAULT_CHARSET, 0, FS(0)},
127   { DEFAULT_CHARSET, 0, FS(0)},
128   { DEFAULT_CHARSET, 0, FS(0)},
129   /* reserved for system */
130   { DEFAULT_CHARSET, 0, FS(0)},
131   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
132 };
133
134 /* ### start build ### */
135 extern WORD CALLBACK FONT_CallTo16_word_llwl(FONTENUMPROC16,LONG,LONG,WORD,LONG);
136 /* ### stop build ### */
137
138 /***********************************************************************
139  *              LOGFONT conversion functions.
140  */
141 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
142 {
143     font16->lfHeight = font32->lfHeight;
144     font16->lfWidth = font32->lfWidth;
145     font16->lfEscapement = font32->lfEscapement;
146     font16->lfOrientation = font32->lfOrientation;
147     font16->lfWeight = font32->lfWeight;
148     font16->lfItalic = font32->lfItalic;
149     font16->lfUnderline = font32->lfUnderline;
150     font16->lfStrikeOut = font32->lfStrikeOut;
151     font16->lfCharSet = font32->lfCharSet;
152     font16->lfOutPrecision = font32->lfOutPrecision;
153     font16->lfClipPrecision = font32->lfClipPrecision;
154     font16->lfQuality = font32->lfQuality;
155     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
156     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
157                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
158     font16->lfFaceName[LF_FACESIZE-1] = 0;
159 }
160
161 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
162 {
163     font32->lfHeight = font16->lfHeight;
164     font32->lfWidth = font16->lfWidth;
165     font32->lfEscapement = font16->lfEscapement;
166     font32->lfOrientation = font16->lfOrientation;
167     font32->lfWeight = font16->lfWeight;
168     font32->lfItalic = font16->lfItalic;
169     font32->lfUnderline = font16->lfUnderline;
170     font32->lfStrikeOut = font16->lfStrikeOut;
171     font32->lfCharSet = font16->lfCharSet;
172     font32->lfOutPrecision = font16->lfOutPrecision;
173     font32->lfClipPrecision = font16->lfClipPrecision;
174     font32->lfQuality = font16->lfQuality;
175     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
176     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
177     font32->lfFaceName[LF_FACESIZE-1] = 0;
178 }
179
180 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
181 {
182     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
183     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
184                         LF_FACESIZE);
185 }
186
187 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
188 {
189     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
190     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
191                         LF_FACESIZE, NULL, NULL);
192 }
193
194 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
195 {
196     FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
197
198     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
199                          font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
200     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
201     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
202                          font16->elfStyle, LF_FACESIZE, NULL, NULL );
203     font16->elfStyle[LF_FACESIZE-1] = '\0';
204     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
205                          font16->elfScript, LF_FACESIZE, NULL, NULL );
206     font16->elfScript[LF_FACESIZE-1] = '\0';
207 }
208
209 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
210 {
211     FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
212
213     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
214                          fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
215     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
216     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
217                          fontA->elfStyle, LF_FACESIZE, NULL, NULL );
218     fontA->elfStyle[LF_FACESIZE-1] = '\0';
219     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
220                          fontA->elfScript, LF_FACESIZE, NULL, NULL );
221     fontA->elfScript[LF_FACESIZE-1] = '\0';
222 }
223
224 /***********************************************************************
225  *              TEXTMETRIC conversion functions.
226  */
227 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
228 {
229     ptmA->tmHeight = ptmW->tmHeight;
230     ptmA->tmAscent = ptmW->tmAscent;
231     ptmA->tmDescent = ptmW->tmDescent;
232     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
233     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
234     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
235     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
236     ptmA->tmWeight = ptmW->tmWeight;
237     ptmA->tmOverhang = ptmW->tmOverhang;
238     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
239     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
240     ptmA->tmFirstChar = ptmW->tmFirstChar;
241     ptmA->tmLastChar = ptmW->tmLastChar;
242     ptmA->tmDefaultChar = ptmW->tmDefaultChar;
243     ptmA->tmBreakChar = ptmW->tmBreakChar;
244     ptmA->tmItalic = ptmW->tmItalic;
245     ptmA->tmUnderlined = ptmW->tmUnderlined;
246     ptmA->tmStruckOut = ptmW->tmStruckOut;
247     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
248     ptmA->tmCharSet = ptmW->tmCharSet;
249 }
250
251
252 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
253 {
254     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
255     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
256     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
257     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
258     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
259     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
260     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
261     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
262     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
263     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
264     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
265     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar;
266     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar;
267     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar;
268     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar;
269     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
270     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
271     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
272     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
273     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
274     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
275     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
276     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
277     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
278     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
279 }
280
281 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
282 {
283     FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
284     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
285     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
286     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
287     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
288     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
289 }
290
291 /***********************************************************************
292  *           CreateFontIndirectA   (GDI32.@)
293  */
294 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
295 {
296     LOGFONTW lfW;
297
298     if (plfA) {
299         FONT_LogFontAToW( plfA, &lfW );
300         return CreateFontIndirectW( &lfW );
301      } else
302         return CreateFontIndirectW( NULL );
303
304 }
305
306 /***********************************************************************
307  *           CreateFontIndirectW   (GDI32.@)
308  */
309 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
310 {
311     HFONT hFont = 0;
312
313     if (plf)
314     {
315         FONTOBJ* fontPtr;
316         if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, &hFont, &font_funcs )))
317         {
318             memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
319
320             TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %04x\n",
321                   plf->lfHeight, plf->lfWidth,
322                   plf->lfEscapement, plf->lfOrientation,
323                   plf->lfPitchAndFamily,
324                   plf->lfOutPrecision, plf->lfClipPrecision,
325                   plf->lfQuality, plf->lfCharSet,
326                   debugstr_w(plf->lfFaceName),
327                   plf->lfWeight > 400 ? "Bold" : "",
328                   plf->lfItalic ? "Italic" : "", hFont);
329
330             if (plf->lfEscapement != plf->lfOrientation) {
331               /* this should really depend on whether GM_ADVANCED is set */
332               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
333               WARN("orientation angle %f set to "
334                    "escapement angle %f for new font %04x\n",
335                    plf->lfOrientation/10., plf->lfEscapement/10., hFont);
336             }
337             GDI_ReleaseObj( hFont );
338         }
339     }
340     else WARN("(NULL) => NULL\n");
341
342     return hFont;
343 }
344
345 /*************************************************************************
346  *           CreateFontA    (GDI32.@)
347  */
348 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
349                               INT orient, INT weight, DWORD italic,
350                               DWORD underline, DWORD strikeout, DWORD charset,
351                               DWORD outpres, DWORD clippres, DWORD quality,
352                               DWORD pitch, LPCSTR name )
353 {
354     LOGFONTA logfont;
355
356     logfont.lfHeight = height;
357     logfont.lfWidth = width;
358     logfont.lfEscapement = esc;
359     logfont.lfOrientation = orient;
360     logfont.lfWeight = weight;
361     logfont.lfItalic = italic;
362     logfont.lfUnderline = underline;
363     logfont.lfStrikeOut = strikeout;
364     logfont.lfCharSet = charset;
365     logfont.lfOutPrecision = outpres;
366     logfont.lfClipPrecision = clippres;
367     logfont.lfQuality = quality;
368     logfont.lfPitchAndFamily = pitch;
369
370     if (name)
371         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
372     else
373         logfont.lfFaceName[0] = '\0';
374
375     return CreateFontIndirectA( &logfont );
376 }
377
378 /*************************************************************************
379  *           CreateFontW    (GDI32.@)
380  */
381 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
382                               INT orient, INT weight, DWORD italic,
383                               DWORD underline, DWORD strikeout, DWORD charset,
384                               DWORD outpres, DWORD clippres, DWORD quality,
385                               DWORD pitch, LPCWSTR name )
386 {
387     LOGFONTW logfont;
388
389     logfont.lfHeight = height;
390     logfont.lfWidth = width;
391     logfont.lfEscapement = esc;
392     logfont.lfOrientation = orient;
393     logfont.lfWeight = weight;
394     logfont.lfItalic = italic;
395     logfont.lfUnderline = underline;
396     logfont.lfStrikeOut = strikeout;
397     logfont.lfCharSet = charset;
398     logfont.lfOutPrecision = outpres;
399     logfont.lfClipPrecision = clippres;
400     logfont.lfQuality = quality;
401     logfont.lfPitchAndFamily = pitch;
402
403     if (name)
404         lstrcpynW(logfont.lfFaceName, name,
405                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
406     else
407         logfont.lfFaceName[0] = '\0';
408
409     return CreateFontIndirectW( &logfont );
410 }
411
412
413 /***********************************************************************
414  *           FONT_SelectObject
415  *
416  * If the driver supports vector fonts we create a gdi font first and
417  * then call the driver to give it a chance to supply its own device
418  * font.  If the driver wants to do this it returns TRUE and we can
419  * delete the gdi font, if the driver wants to use the gdi font it
420  * should return FALSE, to signal an error return GDI_ERROR.  For
421  * drivers that don't support vector fonts they must supply their own
422  * font.
423  */
424 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
425 {
426     HGDIOBJ ret = 0;
427     DC *dc = DC_GetDCPtr( hdc );
428
429     if (!dc) return 0;
430
431     if (dc->hFont != handle || dc->gdiFont == NULL)
432     {
433         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
434             dc->gdiFont = WineEngCreateFontInstance(dc, handle);
435     }
436
437     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
438
439     if (ret && dc->gdiFont) dc->gdiFont = 0;
440
441     if (ret == HGDI_ERROR)
442         ret = 0; /* SelectObject returns 0 on error */
443     else
444     {
445         ret = dc->hFont;
446         dc->hFont = handle;
447     }
448     GDI_ReleaseObj( hdc );
449     return ret;
450 }
451
452
453 /***********************************************************************
454  *           FONT_GetObject16
455  */
456 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
457 {
458     FONTOBJ *font = obj;
459     LOGFONT16 lf16;
460
461     FONT_LogFontWTo16( &font->logfont, &lf16 );
462
463     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
464     memcpy( buffer, &lf16, count );
465     return count;
466 }
467
468 /***********************************************************************
469  *           FONT_GetObjectA
470  */
471 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
472 {
473     FONTOBJ *font = obj;
474     LOGFONTA lfA;
475
476     FONT_LogFontWToA( &font->logfont, &lfA );
477
478     if (count > sizeof(lfA)) count = sizeof(lfA);
479     if(buffer)
480         memcpy( buffer, &lfA, count );
481     return count;
482 }
483
484 /***********************************************************************
485  *           FONT_GetObjectW
486  */
487 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
488 {
489     FONTOBJ *font = obj;
490     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
491     if(buffer)
492         memcpy( buffer, &font->logfont, count );
493     return count;
494 }
495
496
497 /***********************************************************************
498  *           FONT_DeleteObject
499  */
500 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
501 {
502     WineEngDestroyFontInstance( handle );
503     return GDI_FreeObject( handle, obj );
504 }
505
506
507 /***********************************************************************
508  *              FONT_EnumInstance16
509  *
510  * Called by the device driver layer to pass font info
511  * down to the application.
512  */
513 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
514                                 DWORD fType, LPARAM lp )
515 {
516     fontEnum16 *pfe = (fontEnum16*)lp;
517     INT ret = 1;
518     DC *dc;
519
520     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
521         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
522     {
523         FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
524         FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
525         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
526
527         ret = FONT_CallTo16_word_llwl( pfe->lpEnumFunc, pfe->segLogFont, pfe->segTextMetric,
528                                        (UINT16)fType, (LPARAM)pfe->lpData );
529         /* get the lock again and make sure the DC is still valid */
530         dc = DC_GetDCPtr( pfe->hdc );
531         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
532         {
533             if (dc) GDI_ReleaseObj( pfe->hdc );
534             pfe->hdc = 0;  /* make sure we don't try to release it later on */
535             ret = 0;
536         }
537     }
538     return ret;
539 }
540
541 /***********************************************************************
542  *              FONT_EnumInstance
543  */
544 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
545                               DWORD fType, LPARAM lp )
546 {
547     fontEnum32 *pfe = (fontEnum32*)lp;
548     INT ret = 1;
549     DC *dc;
550
551     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
552     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
553         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
554     {
555         /* convert font metrics */
556         ENUMLOGFONTEXA logfont;
557         NEWTEXTMETRICEXA tmA;
558
559         pfe->dwFlags |= ENUM_CALLED;
560         if (!(pfe->dwFlags & ENUM_UNICODE))
561         {
562             FONT_EnumLogFontExWToA( plf, &logfont);
563             FONT_NewTextMetricExWToA( ptm, &tmA );
564             plf = (LPENUMLOGFONTEXW)&logfont;
565             ptm = (NEWTEXTMETRICEXW *)&tmA;
566         }
567         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
568
569         ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
570
571         /* get the lock again and make sure the DC is still valid */
572         dc = DC_GetDCPtr( pfe->hdc );
573         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
574         {
575             if (dc) GDI_ReleaseObj( pfe->hdc );
576             pfe->hdc = 0;  /* make sure we don't try to release it later on */
577             ret = 0;
578         }
579     }
580     return ret;
581 }
582
583 /***********************************************************************
584  *              EnumFontFamiliesEx      (GDI.613)
585  */
586 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
587                                    FONTENUMPROC16 efproc, LPARAM lParam,
588                                    DWORD dwFlags)
589 {
590     fontEnum16 fe16;
591     INT16       retVal = 0;
592     DC*         dc = DC_GetDCPtr( hDC );
593
594     if (!dc) return 0;
595     fe16.hdc = hDC;
596     fe16.dc = dc;
597     fe16.physDev = dc->physDev;
598
599     if (dc->funcs->pEnumDeviceFonts)
600     {
601         NEWTEXTMETRICEX16 tm16;
602         ENUMLOGFONTEX16 lf16;
603         LOGFONTW lfW;
604         FONT_LogFont16ToW(plf, &lfW);
605
606         fe16.lpLogFontParam = plf;
607         fe16.lpEnumFunc = efproc;
608         fe16.lpData = lParam;
609         fe16.lpTextMetric = &tm16;
610         fe16.lpLogFont = &lf16;
611         fe16.segTextMetric = MapLS( &tm16 );
612         fe16.segLogFont = MapLS( &lf16 );
613
614         retVal = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW,
615                                               FONT_EnumInstance16, (LPARAM)&fe16 );
616         UnMapLS( fe16.segTextMetric );
617         UnMapLS( fe16.segLogFont );
618     }
619     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
620     return retVal;
621 }
622
623 /***********************************************************************
624  *              FONT_EnumFontFamiliesEx
625  */
626 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
627                                     FONTENUMPROCW efproc,
628                                     LPARAM lParam, DWORD dwUnicode)
629 {
630     INT ret = 1, ret2;
631     DC *dc = DC_GetDCPtr( hDC );
632     fontEnum32 fe32;
633     BOOL enum_gdi_fonts;
634
635     if (!dc) return 0;
636
637     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
638           plf->lfCharSet);
639     fe32.lpLogFontParam = plf;
640     fe32.lpEnumFunc = efproc;
641     fe32.lpData = lParam;
642     fe32.dwFlags = dwUnicode;
643     fe32.hdc = hDC;
644     fe32.dc = dc;
645     fe32.physDev = dc->physDev;
646
647     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
648
649     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
650     {
651         ret = 0;
652         goto done;
653     }
654
655     if (enum_gdi_fonts)
656         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
657     fe32.dwFlags &= ~ENUM_CALLED;
658     if (ret && dc->funcs->pEnumDeviceFonts) {
659         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
660         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
661             ret = ret2;
662     }
663  done:
664     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
665     return ret;
666 }
667
668 /***********************************************************************
669  *              EnumFontFamiliesExW     (GDI32.@)
670  */
671 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
672                                     FONTENUMPROCW efproc,
673                                     LPARAM lParam, DWORD dwFlags )
674 {
675     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
676 }
677
678 /***********************************************************************
679  *              EnumFontFamiliesExA     (GDI32.@)
680  */
681 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
682                                     FONTENUMPROCA efproc,
683                                     LPARAM lParam, DWORD dwFlags)
684 {
685     LOGFONTW lfW;
686     FONT_LogFontAToW( plf, &lfW );
687
688     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
689 }
690
691 /***********************************************************************
692  *              EnumFontFamilies        (GDI.330)
693  */
694 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
695                                  FONTENUMPROC16 efproc, LPARAM lpData )
696 {
697     LOGFONT16   lf;
698
699     lf.lfCharSet = DEFAULT_CHARSET;
700     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
701     else lf.lfFaceName[0] = '\0';
702
703     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
704 }
705
706 /***********************************************************************
707  *              EnumFontFamiliesA       (GDI32.@)
708  */
709 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
710                                   FONTENUMPROCA efproc, LPARAM lpData )
711 {
712     LOGFONTA    lf;
713
714     lf.lfCharSet = DEFAULT_CHARSET;
715     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
716     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
717
718     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
719 }
720
721 /***********************************************************************
722  *              EnumFontFamiliesW       (GDI32.@)
723  */
724 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
725                                   FONTENUMPROCW efproc, LPARAM lpData )
726 {
727     LOGFONTW  lf;
728
729     lf.lfCharSet = DEFAULT_CHARSET;
730     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
731     else lf.lfFaceName[0] = 0;
732
733     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
734 }
735
736 /***********************************************************************
737  *              EnumFonts               (GDI.70)
738  */
739 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
740                           LPARAM lpData )
741 {
742     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
743 }
744
745 /***********************************************************************
746  *              EnumFontsA              (GDI32.@)
747  */
748 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
749                            LPARAM lpData )
750 {
751     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
752 }
753
754 /***********************************************************************
755  *              EnumFontsW              (GDI32.@)
756  */
757 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
758                            LPARAM lpData )
759 {
760     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
761 }
762
763
764 /***********************************************************************
765  *           GetTextCharacterExtra    (GDI32.@)
766  */
767 INT WINAPI GetTextCharacterExtra( HDC hdc )
768 {
769     INT ret;
770     DC *dc = DC_GetDCPtr( hdc );
771     if (!dc) return 0x80000000;
772     ret = dc->charExtra;
773     GDI_ReleaseObj( hdc );
774     return ret;
775 }
776
777
778 /***********************************************************************
779  *           SetTextCharacterExtra    (GDI32.@)
780  */
781 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
782 {
783     INT prev;
784     DC * dc = DC_GetDCPtr( hdc );
785     if (!dc) return 0x80000000;
786     if (dc->funcs->pSetTextCharacterExtra)
787         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
788     else
789     {
790         prev = dc->charExtra;
791         dc->charExtra = extra;
792     }
793     GDI_ReleaseObj( hdc );
794     return prev;
795 }
796
797
798 /***********************************************************************
799  *           SetTextJustification    (GDI32.@)
800  */
801 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
802 {
803     BOOL ret = TRUE;
804     DC * dc = DC_GetDCPtr( hdc );
805     if (!dc) return FALSE;
806     if (dc->funcs->pSetTextJustification)
807         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
808     else
809     {
810         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
811         if (!extra) breaks = 0;
812         dc->breakTotalExtra = extra;
813         dc->breakCount = breaks;
814         if (breaks)
815         {
816             dc->breakExtra = extra / breaks;
817             dc->breakRem   = extra - (dc->breakCount * dc->breakExtra);
818         }
819         else
820         {
821             dc->breakExtra = 0;
822             dc->breakRem   = 0;
823         }
824     }
825     GDI_ReleaseObj( hdc );
826     return ret;
827 }
828
829
830 /***********************************************************************
831  *           GetTextFaceA    (GDI32.@)
832  */
833 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
834 {
835     INT res = GetTextFaceW(hdc, 0, NULL);
836     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
837     GetTextFaceW( hdc, res, nameW );
838
839     if (name)
840         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count,
841                                    NULL, NULL);
842     else
843         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
844     HeapFree( GetProcessHeap(), 0, nameW );
845     return res;
846 }
847
848 /***********************************************************************
849  *           GetTextFaceW    (GDI32.@)
850  */
851 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
852 {
853     FONTOBJ *font;
854     INT     ret = 0;
855
856     DC * dc = DC_GetDCPtr( hdc );
857     if (!dc) return 0;
858
859     if(dc->gdiFont)
860         ret = WineEngGetTextFace(dc->gdiFont, count, name);
861     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
862     {
863         if (name)
864         {
865             lstrcpynW( name, font->logfont.lfFaceName, count );
866             ret = strlenW(name);
867         }
868         else ret = strlenW(font->logfont.lfFaceName) + 1;
869         GDI_ReleaseObj( dc->hFont );
870     }
871     GDI_ReleaseObj( hdc );
872     return ret;
873 }
874
875
876 /***********************************************************************
877  *           GetTextExtentPoint32A    (GDI32.@)
878  */
879 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
880                                      LPSIZE size )
881 {
882     BOOL ret = FALSE;
883     INT wlen;
884     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
885
886     if (p) {
887         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
888         HeapFree( GetProcessHeap(), 0, p );
889     }
890
891     TRACE("(%08x %s %d %p): returning %ld x %ld\n",
892           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
893     return ret;
894 }
895
896
897 /***********************************************************************
898  * GetTextExtentPoint32W [GDI32.@]  Computes width/height for a string
899  *
900  * Computes width and height of the specified string.
901  *
902  * RETURNS
903  *    Success: TRUE
904  *    Failure: FALSE
905  */
906 BOOL WINAPI GetTextExtentPoint32W(
907     HDC hdc,     /* [in]  Handle of device context */
908     LPCWSTR str,   /* [in]  Address of text string */
909     INT count,   /* [in]  Number of characters in string */
910     LPSIZE size) /* [out] Address of structure for string size */
911 {
912     BOOL ret = FALSE;
913     DC * dc = DC_GetDCPtr( hdc );
914     if (!dc) return FALSE;
915
916     if(dc->gdiFont) {
917         ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
918         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
919         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
920     }
921     else if(dc->funcs->pGetTextExtentPoint)
922         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
923
924     GDI_ReleaseObj( hdc );
925
926     TRACE("(%08x %s %d %p): returning %ld x %ld\n",
927           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
928     return ret;
929 }
930
931 /***********************************************************************
932  * GetTextExtentPointI [GDI32.@]
933  *
934  * Computes width and height of the array of glyph indices.
935  *
936  * RETURNS
937  *    Success: TRUE
938  *    Failure: FALSE
939  */
940 BOOL WINAPI GetTextExtentPointI(
941     HDC hdc,     /* [in]  Handle of device context */
942     const WORD *indices,   /* [in]  Address of glyph index array */
943     INT count,   /* [in]  Number of glyphs in array */
944     LPSIZE size) /* [out] Address of structure for string size */
945 {
946     BOOL ret = FALSE;
947     DC * dc = DC_GetDCPtr( hdc );
948     if (!dc) return FALSE;
949
950     if(dc->gdiFont) {
951         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
952         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
953         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
954     }
955     else if(dc->funcs->pGetTextExtentPoint) {
956         FIXME("calling GetTextExtentPoint\n");
957         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
958     }
959
960     GDI_ReleaseObj( hdc );
961
962     TRACE("(%08x %p %d %p): returning %ld x %ld\n",
963           hdc, indices, count, size, size->cx, size->cy );
964     return ret;
965 }
966
967
968 /***********************************************************************
969  *           GetTextExtentPointA    (GDI32.@)
970  */
971 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
972                                           LPSIZE size )
973 {
974     TRACE("not bug compatible.\n");
975     return GetTextExtentPoint32A( hdc, str, count, size );
976 }
977
978 /***********************************************************************
979  *           GetTextExtentPointW   (GDI32.@)
980  */
981 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
982                                           LPSIZE size )
983 {
984     TRACE("not bug compatible.\n");
985     return GetTextExtentPoint32W( hdc, str, count, size );
986 }
987
988
989 /***********************************************************************
990  *           GetTextExtentExPointA    (GDI32.@)
991  */
992 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
993                                    INT maxExt, LPINT lpnFit,
994                                    LPINT alpDx, LPSIZE size )
995 {
996     BOOL ret;
997     INT wlen;
998     LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
999     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1000     HeapFree( GetProcessHeap(), 0, p );
1001     return ret;
1002 }
1003
1004
1005 /***********************************************************************
1006  *           GetTextExtentExPointW    (GDI32.@)
1007  *
1008  * Return the size of the string as it would be if it was output properly by
1009  * e.g. TextOut.
1010  *
1011  * This should include
1012  * - Intercharacter spacing
1013  * - justification spacing (not yet done)
1014  * - kerning? see below
1015  *
1016  * Kerning.  Since kerning would be carried out by the rendering code it should
1017  * be done by the driver.  However they don't support it yet.  Also I am not
1018  * yet persuaded that (certainly under Win95) any kerning is actually done.
1019  *
1020  * str: According to MSDN this should be null-terminated.  That is not true; a
1021  *      null will not terminate it early.
1022  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1023  *       than count.  I have seen it be either the size of the full string or
1024  *       1 less than the size of the full string.  I have not seen it bear any
1025  *       resemblance to the portion that would fit.
1026  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1027  *         trailing intercharacter spacing and any trailing justification.
1028  *
1029  * FIXME
1030  * Currently we do this by measuring each character etc.  We should do it by
1031  * passing the request to the driver, perhaps by extending the
1032  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1033  * thinking about kerning issues and rounding issues in the justification.
1034  */
1035
1036 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1037                                    INT maxExt, LPINT lpnFit,
1038                                    LPINT alpDx, LPSIZE size )
1039 {
1040     int index, nFit, extent;
1041     SIZE tSize;
1042     BOOL ret = FALSE;
1043
1044     TRACE("(%08x, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1045
1046     size->cx = size->cy = nFit = extent = 0;
1047     for(index = 0; index < count; index++)
1048     {
1049         if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1050         /* GetTextExtentPoint includes intercharacter spacing. */
1051         /* FIXME - justification needs doing yet.  Remember that the base
1052          * data will not be in logical coordinates.
1053          */
1054         extent += tSize.cx;
1055         if( !lpnFit || extent <= maxExt )
1056         /* It is allowed to be equal. */
1057         {
1058             nFit++;
1059             if( alpDx ) alpDx[index] = extent;
1060         }
1061         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1062         str++;
1063     }
1064     size->cx = extent;
1065     if(lpnFit) *lpnFit = nFit;
1066     ret = TRUE;
1067
1068     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1069
1070 done:
1071     return ret;
1072 }
1073
1074 /***********************************************************************
1075  *           GetTextMetricsA    (GDI32.@)
1076  */
1077 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1078 {
1079     TEXTMETRICW tm32;
1080
1081     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1082     FONT_TextMetricWToA( &tm32, metrics );
1083     return TRUE;
1084 }
1085
1086 /***********************************************************************
1087  *           GetTextMetricsW    (GDI32.@)
1088  */
1089 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1090 {
1091     BOOL ret = FALSE;
1092     DC * dc = DC_GetDCPtr( hdc );
1093     if (!dc) return FALSE;
1094
1095     if (dc->gdiFont)
1096         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1097     else if (dc->funcs->pGetTextMetrics)
1098         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1099
1100     if (ret)
1101     {
1102     /* device layer returns values in device units
1103      * therefore we have to convert them to logical */
1104
1105 #define WDPTOLP(x) ((x<0)?                                      \
1106                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1107                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1108 #define HDPTOLP(y) ((y<0)?                                      \
1109                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1110                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1111
1112     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1113     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1114     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1115     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1116     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1117     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1118     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1119     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1120         ret = TRUE;
1121 #undef WDPTOLP
1122 #undef HDPTOLP
1123     TRACE("text metrics:\n"
1124           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1125           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1126           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1127           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1128           "    PitchAndFamily = %02x\n"
1129           "    --------------------\n"
1130           "    InternalLeading = %li\n"
1131           "    Ascent = %li\n"
1132           "    Descent = %li\n"
1133           "    Height = %li\n",
1134           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1135           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1136           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1137           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1138           metrics->tmPitchAndFamily,
1139           metrics->tmInternalLeading,
1140           metrics->tmAscent,
1141           metrics->tmDescent,
1142           metrics->tmHeight );
1143     }
1144     GDI_ReleaseObj( hdc );
1145     return ret;
1146 }
1147
1148
1149 /***********************************************************************
1150  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1151  *
1152  * NOTES
1153  *    lpOTM should be LPOUTLINETEXTMETRIC
1154  *
1155  * RETURNS
1156  *    Success: Non-zero or size of required buffer
1157  *    Failure: 0
1158  */
1159 UINT16 WINAPI GetOutlineTextMetrics16(
1160     HDC16 hdc,    /* [in]  Handle of device context */
1161     UINT16 cbData, /* [in]  Size of metric data array */
1162     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1163 {
1164     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1165     return 0;
1166 }
1167
1168
1169 /***********************************************************************
1170  *              GetOutlineTextMetricsA (GDI32.@)
1171  * Gets metrics for TrueType fonts.
1172  *
1173  *
1174  * RETURNS
1175  *    Success: Non-zero or size of required buffer
1176  *    Failure: 0
1177  */
1178 UINT WINAPI GetOutlineTextMetricsA(
1179     HDC hdc,    /* [in]  Handle of device context */
1180     UINT cbData, /* [in]  Size of metric data array */
1181     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1182 {
1183     char buf[512], *ptr;
1184     UINT ret, needed;
1185     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1186     INT left, len;
1187
1188     if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1189         if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1190             return 0;
1191         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1192         GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1193     }
1194
1195     needed = sizeof(OUTLINETEXTMETRICA);
1196     if(lpOTMW->otmpFamilyName)
1197         needed += WideCharToMultiByte(CP_ACP, 0,
1198            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1199                                       NULL, 0, NULL, NULL);
1200     if(lpOTMW->otmpFaceName)
1201         needed += WideCharToMultiByte(CP_ACP, 0,
1202            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1203                                       NULL, 0, NULL, NULL);
1204     if(lpOTMW->otmpStyleName)
1205         needed += WideCharToMultiByte(CP_ACP, 0,
1206            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1207                                       NULL, 0, NULL, NULL);
1208     if(lpOTMW->otmpFullName)
1209         needed += WideCharToMultiByte(CP_ACP, 0,
1210            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1211                                       NULL, 0, NULL, NULL);
1212
1213     if(!lpOTM) {
1214         ret = needed;
1215         goto end;
1216     }
1217
1218     if(needed > cbData) {
1219         ret = 0;
1220         goto end;
1221     }
1222
1223
1224     lpOTM->otmSize = needed;
1225     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1226     lpOTM->otmFiller = 0;
1227     lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1228     lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1229     lpOTM->otmfsType = lpOTMW->otmfsType;
1230     lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1231     lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1232     lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1233     lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1234     lpOTM->otmAscent = lpOTMW->otmAscent;
1235     lpOTM->otmDescent = lpOTMW->otmDescent;
1236     lpOTM->otmLineGap = lpOTMW->otmLineGap;
1237     lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1238     lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1239     lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1240     lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1241     lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1242     lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1243     lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1244     lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1245     lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1246     lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1247     lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1248     lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1249     lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1250     lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1251     lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1252
1253
1254     ptr = (char*)(lpOTM + 1);
1255     left = needed - sizeof(*lpOTM);
1256
1257     if(lpOTMW->otmpFamilyName) {
1258         lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1259         len = WideCharToMultiByte(CP_ACP, 0,
1260              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1261                                   ptr, left, NULL, NULL);
1262         left -= len;
1263         ptr += len;
1264     } else
1265         lpOTM->otmpFamilyName = 0;
1266
1267     if(lpOTMW->otmpFaceName) {
1268         lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1269         len = WideCharToMultiByte(CP_ACP, 0,
1270              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1271                                   ptr, left, NULL, NULL);
1272         left -= len;
1273         ptr += len;
1274     } else
1275         lpOTM->otmpFaceName = 0;
1276
1277     if(lpOTMW->otmpStyleName) {
1278         lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1279         len = WideCharToMultiByte(CP_ACP, 0,
1280              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1281                                   ptr, left, NULL, NULL);
1282         left -= len;
1283         ptr += len;
1284     } else
1285         lpOTM->otmpStyleName = 0;
1286
1287     if(lpOTMW->otmpFullName) {
1288         lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1289         len = WideCharToMultiByte(CP_ACP, 0,
1290              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1291                                   ptr, left, NULL, NULL);
1292         left -= len;
1293     } else
1294         lpOTM->otmpFullName = 0;
1295
1296     assert(left == 0);
1297
1298     ret = needed;
1299
1300 end:
1301     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1302         HeapFree(GetProcessHeap(), 0, lpOTMW);
1303
1304     return ret;
1305 }
1306
1307
1308 /***********************************************************************
1309  *           GetOutlineTextMetricsW [GDI32.@]
1310  */
1311 UINT WINAPI GetOutlineTextMetricsW(
1312     HDC hdc,    /* [in]  Handle of device context */
1313     UINT cbData, /* [in]  Size of metric data array */
1314     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1315 {
1316     DC *dc = DC_GetDCPtr( hdc );
1317     UINT ret;
1318
1319     TRACE("(%d,%d,%p)\n", hdc, cbData, lpOTM);
1320     if(!dc) return 0;
1321
1322     if(dc->gdiFont) {
1323         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1324         if(ret && ret <= cbData) {
1325 #define WDPTOLP(x) ((x<0)?                                      \
1326                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1327                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1328 #define HDPTOLP(y) ((y<0)?                                      \
1329                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1330                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1331
1332             lpOTM->otmTextMetrics.tmHeight           = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1333             lpOTM->otmTextMetrics.tmAscent           = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1334             lpOTM->otmTextMetrics.tmDescent          = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1335             lpOTM->otmTextMetrics.tmInternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1336             lpOTM->otmTextMetrics.tmExternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1337             lpOTM->otmTextMetrics.tmAveCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1338             lpOTM->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1339             lpOTM->otmTextMetrics.tmOverhang         = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1340             lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1341             lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1342             lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1343             lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1344             lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1345             lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1346             lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1347             lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1348             lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1349             lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1350             lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1351             lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1352             lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1353             lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1354             lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1355             lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1356             lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1357             lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1358             lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1359             lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1360             lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1361             lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1362             lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1363             lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1364 #undef WDPTOLP
1365 #undef HDPTOLP
1366         }
1367     }
1368
1369     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1370               but really this should just be a return 0. */
1371
1372         ret = sizeof(*lpOTM);
1373         if (lpOTM) {
1374             if(cbData < ret)
1375                 ret = 0;
1376             else {
1377                 memset(lpOTM, 0, ret);
1378                 lpOTM->otmSize = sizeof(*lpOTM);
1379                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1380                 /*
1381                   Further fill of the structure not implemented,
1382                   Needs real values for the structure members
1383                 */
1384             }
1385         }
1386     }
1387     GDI_ReleaseObj(hdc);
1388     return ret;
1389 }
1390
1391
1392 /***********************************************************************
1393  *           GetCharWidthW      (GDI32.@)
1394  *           GetCharWidth32W    (GDI32.@)
1395  */
1396 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1397                                LPINT buffer )
1398 {
1399     UINT i, extra;
1400     BOOL ret = FALSE;
1401     DC * dc = DC_GetDCPtr( hdc );
1402     if (!dc) return FALSE;
1403
1404     if (dc->gdiFont)
1405         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1406     else if (dc->funcs->pGetCharWidth)
1407         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1408
1409     if (ret)
1410     {
1411         /* convert device units to logical */
1412
1413         extra = dc->vportExtX >> 1;
1414         for( i = firstChar; i <= lastChar; i++, buffer++ )
1415             *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1416         ret = TRUE;
1417     }
1418     GDI_ReleaseObj( hdc );
1419     return ret;
1420 }
1421
1422
1423 /***********************************************************************
1424  *           GetCharWidthA      (GDI32.@)
1425  *           GetCharWidth32A    (GDI32.@)
1426  */
1427 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1428                                LPINT buffer )
1429 {
1430     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1431     LPSTR str;
1432     LPWSTR wstr;
1433     BOOL ret = TRUE;
1434
1435     if(count <= 0) return FALSE;
1436
1437     str = HeapAlloc(GetProcessHeap(), 0, count);
1438     for(i = 0; i < count; i++)
1439         str[i] = (BYTE)(firstChar + i);
1440
1441     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1442
1443     for(i = 0; i < wlen; i++)
1444     {
1445         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1446         {
1447             ret = FALSE;
1448             break;
1449         }
1450         buffer++;
1451     }
1452
1453     HeapFree(GetProcessHeap(), 0, str);
1454     HeapFree(GetProcessHeap(), 0, wstr);
1455
1456     return ret;
1457 }
1458
1459
1460 /* FIXME: all following APIs ******************************************/
1461
1462
1463 /***********************************************************************
1464  *           SetMapperFlags    (GDI32.@)
1465  */
1466 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1467 {
1468     DC *dc = DC_GetDCPtr( hDC );
1469     DWORD ret = 0;
1470     if(!dc) return 0;
1471     if(dc->funcs->pSetMapperFlags)
1472         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1473     else
1474         FIXME("(0x%04x, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1475     GDI_ReleaseObj( hDC );
1476     return ret;
1477 }
1478
1479 /***********************************************************************
1480  *          GetAspectRatioFilterEx  (GDI.486)
1481  */
1482 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1483 {
1484   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1485   return FALSE;
1486 }
1487
1488 /***********************************************************************
1489  *          GetAspectRatioFilterEx  (GDI32.@)
1490  */
1491 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1492 {
1493   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1494   return FALSE;
1495 }
1496
1497
1498 /***********************************************************************
1499  *           GetCharABCWidthsA   (GDI32.@)
1500  */
1501 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1502                                   LPABC abc )
1503 {
1504     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1505     LPSTR str;
1506     LPWSTR wstr;
1507     BOOL ret = TRUE;
1508
1509     if(count <= 0) return FALSE;
1510
1511     str = HeapAlloc(GetProcessHeap(), 0, count);
1512     for(i = 0; i < count; i++)
1513         str[i] = (BYTE)(firstChar + i);
1514
1515     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1516
1517     for(i = 0; i < wlen; i++)
1518     {
1519         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1520         {
1521             ret = FALSE;
1522             break;
1523         }
1524         abc++;
1525     }
1526
1527     HeapFree(GetProcessHeap(), 0, str);
1528     HeapFree(GetProcessHeap(), 0, wstr);
1529
1530     return ret;
1531 }
1532
1533
1534 /******************************************************************************
1535  * GetCharABCWidthsW [GDI32.@]  Retrieves widths of characters in range
1536  *
1537  * PARAMS
1538  *    hdc       [I] Handle of device context
1539  *    firstChar [I] First character in range to query
1540  *    lastChar  [I] Last character in range to query
1541  *    abc       [O] Address of character-width structure
1542  *
1543  * NOTES
1544  *    Only works with TrueType fonts
1545  *
1546  * RETURNS
1547  *    Success: TRUE
1548  *    Failure: FALSE
1549  */
1550 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1551                                    LPABC abc )
1552 {
1553     DC *dc = DC_GetDCPtr(hdc);
1554     int         i;
1555     GLYPHMETRICS gm;
1556     BOOL ret = FALSE;
1557
1558     if(dc->gdiFont) {
1559         for (i=firstChar;i<=lastChar;i++) {
1560             GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1561             abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1562             abc[i-firstChar].abcB = gm.gmBlackBoxX;
1563             abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1564         }
1565         ret = TRUE;
1566     }
1567     GDI_ReleaseObj(hdc);
1568     return ret;
1569 }
1570
1571
1572 /***********************************************************************
1573  *           GetGlyphOutline    (GDI.309)
1574  */
1575 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1576                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1577                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1578 {
1579     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1580           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1581     return (DWORD)-1; /* failure */
1582 }
1583
1584
1585 /***********************************************************************
1586  *           GetGlyphOutlineA    (GDI32.@)
1587  */
1588 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1589                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1590                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1591 {
1592     LPWSTR p = NULL;
1593     DWORD ret;
1594     UINT c;
1595
1596     if(!(fuFormat & GGO_GLYPH_INDEX)) {
1597         p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1598         c = p[0];
1599     } else
1600         c = uChar;
1601     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1602                            lpmat2);
1603     if(p)
1604         HeapFree(GetProcessHeap(), 0, p);
1605     return ret;
1606 }
1607
1608 /***********************************************************************
1609  *           GetGlyphOutlineW    (GDI32.@)
1610  */
1611 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1612                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1613                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1614 {
1615     DC *dc = DC_GetDCPtr(hdc);
1616     DWORD ret;
1617
1618     TRACE("(%04x, %04x, %04x, %p, %ld, %p, %p)\n",
1619           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1620
1621     if(!dc) return GDI_ERROR;
1622
1623     if(dc->gdiFont)
1624       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1625                                    cbBuffer, lpBuffer, lpmat2);
1626     else
1627       ret = GDI_ERROR;
1628
1629     GDI_ReleaseObj(hdc);
1630     return ret;
1631 }
1632
1633
1634 /***********************************************************************
1635  *           CreateScalableFontResourceA   (GDI32.@)
1636  */
1637 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1638                                              LPCSTR lpszResourceFile,
1639                                              LPCSTR lpszFontFile,
1640                                              LPCSTR lpszCurrentPath )
1641 {
1642     HANDLE f;
1643
1644     /* fHidden=1 - only visible for the calling app, read-only, not
1645      * enumbered with EnumFonts/EnumFontFamilies
1646      * lpszCurrentPath can be NULL
1647      */
1648     FIXME("(%ld,%s,%s,%s): stub\n",
1649           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1650           debugstr_a(lpszCurrentPath) );
1651
1652     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1653     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1654         CloseHandle(f);
1655         SetLastError(ERROR_FILE_EXISTS);
1656         return FALSE;
1657     }
1658     return FALSE; /* create failed */
1659 }
1660
1661 /***********************************************************************
1662  *           CreateScalableFontResourceW   (GDI32.@)
1663  */
1664 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1665                                              LPCWSTR lpszResourceFile,
1666                                              LPCWSTR lpszFontFile,
1667                                              LPCWSTR lpszCurrentPath )
1668 {
1669     FIXME("(%ld,%p,%p,%p): stub\n",
1670           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1671     return FALSE; /* create failed */
1672 }
1673
1674
1675 /*************************************************************************
1676  *             GetRasterizerCaps   (GDI32.@)
1677  */
1678 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1679 {
1680   lprs->nSize = sizeof(RASTERIZER_STATUS);
1681   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1682   lprs->nLanguageID = 0;
1683   return TRUE;
1684 }
1685
1686
1687 /*************************************************************************
1688  *             GetKerningPairsA   (GDI32.@)
1689  */
1690 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs, LPKERNINGPAIR lpKerningPairs )
1691 {
1692     int i;
1693     FIXME("(%x,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1694     for (i = 0; i < cPairs; i++)
1695         lpKerningPairs[i].iKernAmount = 0;
1696     return 0;
1697 }
1698
1699
1700 /*************************************************************************
1701  *             GetKerningPairsW   (GDI32.@)
1702  */
1703 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1704                                  LPKERNINGPAIR lpKerningPairs )
1705 {
1706     return GetKerningPairsA( hDC, cPairs, lpKerningPairs );
1707 }
1708
1709 /*************************************************************************
1710  * TranslateCharsetInfo [GDI32.@]
1711  *
1712  * Fills a CHARSETINFO structure for a character set, code page, or
1713  * font. This allows making the correspondance between different labelings
1714  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1715  * of the same encoding.
1716  *
1717  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1718  * only one codepage should be set in *lpSrc.
1719  *
1720  * RETURNS
1721  *   TRUE on success, FALSE on failure.
1722  *
1723  */
1724 BOOL WINAPI TranslateCharsetInfo(
1725   LPDWORD lpSrc, /* [in]
1726        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1727        if flags == TCI_SRCCHARSET: a character set value
1728        if flags == TCI_SRCCODEPAGE: a code page value
1729                  */
1730   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1731   DWORD flags /* [in] determines interpretation of lpSrc */
1732 ) {
1733     int index = 0;
1734     switch (flags) {
1735     case TCI_SRCFONTSIG:
1736         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1737       break;
1738     case TCI_SRCCODEPAGE:
1739       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1740       break;
1741     case TCI_SRCCHARSET:
1742       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1743       break;
1744     default:
1745       return FALSE;
1746     }
1747     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1748     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1749     return TRUE;
1750 }
1751
1752 /*************************************************************************
1753  *             GetFontLanguageInfo   (GDI32.@)
1754  */
1755 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1756 {
1757         FONTSIGNATURE fontsig;
1758         static const DWORD GCP_DBCS_MASK=0x003F0000,
1759                 GCP_DIACRITIC_MASK=0x00000000,
1760                 FLI_GLYPHS_MASK=0x00000000,
1761                 GCP_GLYPHSHAPE_MASK=0x00000040,
1762                 GCP_KASHIDA_MASK=0x00000000,
1763                 GCP_LIGATE_MASK=0x00000000,
1764                 GCP_USEKERNING_MASK=0x00000000,
1765                 GCP_REORDER_MASK=0x00000060;
1766
1767         DWORD result=0;
1768
1769         GetTextCharsetInfo( hdc, &fontsig, 0 );
1770         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1771
1772         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1773                 result|=GCP_DBCS;
1774
1775         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1776                 result|=GCP_DIACRITIC;
1777
1778         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1779                 result|=FLI_GLYPHS;
1780
1781         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1782                 result|=GCP_GLYPHSHAPE;
1783
1784         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1785                 result|=GCP_KASHIDA;
1786
1787         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1788                 result|=GCP_LIGATE;
1789
1790         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1791                 result|=GCP_USEKERNING;
1792
1793         if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1794                 result|=GCP_REORDER;
1795
1796         return result;
1797 }
1798
1799
1800 /*************************************************************************
1801  * GetFontData [GDI32.@] Retrieve data for TrueType font
1802  *
1803  * RETURNS
1804  *
1805  * success: Number of bytes returned
1806  * failure: GDI_ERROR
1807  *
1808  * NOTES
1809  *
1810  * Calls SetLastError()
1811  *
1812  */
1813 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1814     LPVOID buffer, DWORD length)
1815 {
1816     DC *dc = DC_GetDCPtr(hdc);
1817     DWORD ret = GDI_ERROR;
1818
1819     if(!dc) return GDI_ERROR;
1820
1821     if(dc->gdiFont)
1822       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1823
1824     GDI_ReleaseObj(hdc);
1825     return ret;
1826 }
1827
1828 /*************************************************************************
1829  * GetGlyphIndicesA [GDI32.@]
1830  */
1831 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1832                               LPWORD pgi, DWORD flags)
1833 {
1834     DWORD ret;
1835     WCHAR *lpstrW;
1836     INT countW;
1837
1838     TRACE("(%04x, %s, %d, %p, 0x%lx)\n",
1839         hdc, debugstr_an(lpstr, count), count, pgi, flags);
1840
1841     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1842     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1843     HeapFree(GetProcessHeap(), 0, lpstrW);
1844
1845     return ret;
1846 }
1847
1848 /*************************************************************************
1849  * GetGlyphIndicesW [GDI32.@]
1850  */
1851 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1852                               LPWORD pgi, DWORD flags)
1853 {
1854     DC *dc = DC_GetDCPtr(hdc);
1855     DWORD ret = GDI_ERROR;
1856
1857     TRACE("(%04x, %s, %d, %p, 0x%lx)\n",
1858         hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1859
1860     if(!dc) return GDI_ERROR;
1861
1862     if(dc->gdiFont)
1863         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1864
1865     GDI_ReleaseObj(hdc);
1866     return ret;
1867 }
1868
1869 /*************************************************************************
1870  * GetCharacterPlacementA [GDI32.@]
1871  *
1872  * NOTES:
1873  *  the web browser control of ie4 calls this with dwFlags=0
1874  */
1875 DWORD WINAPI
1876 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1877                          INT nMaxExtent, GCP_RESULTSA *lpResults,
1878                          DWORD dwFlags)
1879 {
1880     WCHAR *lpStringW;
1881     INT uCountW, i;
1882     GCP_RESULTSW resultsW;
1883     DWORD ret;
1884     UINT font_cp;
1885
1886     TRACE("%s, %d, %d, 0x%08lx\n",
1887           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1888
1889     /* both structs are equal in size */
1890     memcpy(&resultsW, lpResults, sizeof(resultsW));
1891
1892     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1893     if(lpResults->lpOutString)
1894         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1895
1896     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1897
1898     if(lpResults->lpOutString) {
1899         if(font_cp != CP_SYMBOL)
1900             WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1901                                 lpResults->lpOutString, uCount, NULL, NULL );
1902         else
1903             for(i = 0; i < uCount; i++)
1904                 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1905     }
1906
1907     HeapFree(GetProcessHeap(), 0, lpStringW);
1908     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1909
1910     return ret;
1911 }
1912
1913 /*************************************************************************
1914  * GetCharacterPlacementW [GDI32.@]
1915  *
1916  *   Retrieve information about a string. This includes the width, reordering,
1917  *   Glyphing and so on.
1918  *
1919  * RETURNS
1920  *
1921  *   The width and height of the string if succesful, 0 if failed.
1922  *
1923  * BUGS
1924  *
1925  *   All flags except GCP_REORDER are not yet implemented.
1926  *   Reordering is not 100% complient to the Windows BiDi method.
1927  *   Caret positioning is not yet implemented.
1928  *   Classes are not yet implemented.
1929  *
1930  */
1931 DWORD WINAPI
1932 GetCharacterPlacementW(
1933                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
1934                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
1935                 INT uCount,             /* [in] Number of WORDS in string. */
1936                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
1937                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1938                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
1939                 )
1940 {
1941     DWORD ret=0;
1942     SIZE size;
1943     UINT i, nSet;
1944
1945     TRACE("%s, %d, %d, 0x%08lx\n",
1946           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
1947
1948     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1949           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1950             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
1951             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1952             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
1953
1954     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
1955     if(lpResults->lpCaretPos)   FIXME("caret positions not implemented\n");
1956     if(lpResults->lpClass)      FIXME("classes not implemented\n");
1957
1958         nSet = (UINT)uCount;
1959         if(nSet > lpResults->nGlyphs)
1960                 nSet = lpResults->nGlyphs;
1961
1962         /* return number of initialized fields */
1963         lpResults->nGlyphs = nSet;
1964
1965         if(dwFlags==0)
1966         {
1967                 /* Treat the case where no special handling was requested in a fastpath way */
1968                 /* copy will do if the GCP_REORDER flag is not set */
1969                 if(lpResults->lpOutString)
1970                         for(i=0; i<nSet && lpString[i]!=0; ++i )
1971                                 lpResults->lpOutString[i]=lpString[i];
1972
1973                 if(lpResults->lpOrder)
1974                 {
1975                         for(i = 0; i < nSet; i++)
1976                                 lpResults->lpOrder[i] = i;
1977                 }
1978         }
1979
1980         if((dwFlags&GCP_REORDER)!=0)
1981         {
1982                 WORD *pwCharType;
1983                 int run_end;
1984                 /* Keep a static table that translates the C2 types to something meaningful */
1985                 /* 1 - left to right
1986                  * -1 - right to left
1987                  * 0 - neutral
1988                  */
1989                 static const int chardir[]={ 0, 1, -1, 1, 1, 1, -1, 1, 0, 0, 0, 0 };
1990
1991                 WARN("The BiDi algorythm doesn't conform to Windows' yet\n");
1992                 if( (pwCharType=HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)))==NULL )
1993                 {
1994                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1995
1996                         return 0;
1997                 }
1998
1999                 /* Fill in the order array with directionality values */
2000                 GetStringTypeW(CT_CTYPE2, lpString, uCount, pwCharType);
2001
2002                 /* The complete and correct (at least according to MS) BiDi algorythm is not
2003                  * yet implemented here. Instead, we just make sure that consecutive runs of
2004                  * the same direction (or neutral) are ordered correctly. We also assign Neutrals
2005                  * that are between runs of opposing directions the base (ok, always LTR) dir.
2006                  * While this is a LONG way from a BiDi algorithm, it does produce more or less
2007                  * readable results.
2008                  */
2009                 for( i=0; i<uCount; i+=run_end )
2010                 {
2011                         for( run_end=1; i+run_end<uCount &&
2012                              (chardir[pwCharType[i+run_end]]==chardir[pwCharType[i]] ||
2013                              chardir[pwCharType[i+run_end]]==0); ++run_end )
2014                                 ;
2015
2016                         if( chardir[pwCharType[i]]==1 || chardir[pwCharType[i]]==0 )
2017                         {
2018                                 /* A LTR run */
2019                                 if(lpResults->lpOutString)
2020                                 {
2021                                         int j;
2022                                         for( j=0; j<run_end; j++ )
2023                                         {
2024                                                 lpResults->lpOutString[i+j]=lpString[i+j];
2025                                         }
2026                                 }
2027
2028                                 if(lpResults->lpOrder)
2029                                 {
2030                                         int j;
2031                                         for( j=0; j<run_end; j++ )
2032                                                 lpResults->lpOrder[i+j] = i+j;
2033                                 }
2034                         } else
2035                         {
2036                                 /* A RTL run */
2037
2038                                 /* Since, at this stage, the paragraph context is always LTR,
2039                                  * remove any neutrals from the end of this run.
2040                                  */
2041                                 if( chardir[pwCharType[i]]!=0 )
2042                                         while( chardir[pwCharType[i+run_end-1]]==0 )
2043                                                 --run_end;
2044
2045                                 if(lpResults->lpOutString)
2046                                 {
2047                                         int j;
2048                                         for( j=0; j<run_end; j++ )
2049                                         {
2050                                                 lpResults->lpOutString[i+j]=lpString[i+run_end-j-1];
2051                                         }
2052                                 }
2053
2054                                 if(lpResults->lpOrder)
2055                                 {
2056                                         int j;
2057                                         for( j=0; j<run_end; j++ )
2058                                                 lpResults->lpOrder[i+j] = i+run_end-j-1;
2059                                 }
2060                         }
2061                 }
2062
2063                 HeapFree(GetProcessHeap(), 0, pwCharType);
2064         }
2065
2066         /* FIXME: Will use the placement chars */
2067         if (lpResults->lpDx)
2068         {
2069                 int c;
2070                 for (i = 0; i < nSet; i++)
2071                 {
2072                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2073                                 lpResults->lpDx[i]= c;
2074                 }
2075         }
2076
2077     if(lpResults->lpGlyphs)
2078         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2079
2080     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2081       ret = MAKELONG(size.cx, size.cy);
2082
2083     return ret;
2084 }
2085
2086 /*************************************************************************
2087  *      GetCharABCWidthsFloatA [GDI32.@]
2088  */
2089 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2090                                         LPABCFLOAT lpABCF)
2091 {
2092        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2093        return 0;
2094 }
2095
2096 /*************************************************************************
2097  *      GetCharABCWidthsFloatW [GDI32.@]
2098  */
2099 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2100                                         UINT iLastChar, LPABCFLOAT lpABCF)
2101 {
2102        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2103        return 0;
2104 }
2105
2106 /*************************************************************************
2107  *      GetCharWidthFloatA [GDI32.@]
2108  */
2109 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2110                                     UINT iLastChar, PFLOAT pxBuffer)
2111 {
2112        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2113        return 0;
2114 }
2115
2116 /*************************************************************************
2117  *      GetCharWidthFloatW [GDI32.@]
2118  */
2119 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2120                                     UINT iLastChar, PFLOAT pxBuffer)
2121 {
2122        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2123        return 0;
2124 }
2125
2126
2127 /***********************************************************************
2128  *                                                                     *
2129  *           Font Resource API                                         *
2130  *                                                                     *
2131  ***********************************************************************/
2132
2133 /***********************************************************************
2134  *           AddFontResourceA    (GDI32.@)
2135  */
2136 INT WINAPI AddFontResourceA( LPCSTR str )
2137 {
2138     return AddFontResourceExA( str, 0, NULL);
2139 }
2140
2141 /***********************************************************************
2142  *           AddFontResourceW    (GDI32.@)
2143  */
2144 INT WINAPI AddFontResourceW( LPCWSTR str )
2145 {
2146     return AddFontResourceExW(str, 0, NULL);
2147 }
2148
2149
2150 /***********************************************************************
2151  *           AddFontResourceExA    (GDI32.@)
2152  */
2153 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2154 {
2155     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2156     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2157     INT ret;
2158
2159     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2160     ret = AddFontResourceExW(strW, fl, pdv);
2161     HeapFree(GetProcessHeap(), 0, strW);
2162     return ret;
2163 }
2164
2165 /***********************************************************************
2166  *           AddFontResourceExW    (GDI32.@)
2167  */
2168 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2169 {
2170     return WineEngAddFontResourceEx(str, fl, pdv);
2171 }
2172
2173 /***********************************************************************
2174  *           RemoveFontResourceA    (GDI32.@)
2175  */
2176 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2177 {
2178     return RemoveFontResourceExA(str, 0, 0);
2179 }
2180
2181 /***********************************************************************
2182  *           RemoveFontResourceW    (GDI32.@)
2183  */
2184 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2185 {
2186     return RemoveFontResourceExW(str, 0, 0);
2187 }
2188
2189 /***********************************************************************
2190  *           RemoveFontResourceExA    (GDI32.@)
2191  */
2192 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2193 {
2194     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2195     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2196     INT ret;
2197
2198     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2199     ret = RemoveFontResourceExW(strW, fl, pdv);
2200     HeapFree(GetProcessHeap(), 0, strW);
2201     return ret;
2202 }
2203
2204 /***********************************************************************
2205  *           RemoveFontResourceExW    (GDI32.@)
2206  */
2207 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2208 {
2209     return WineEngRemoveFontResourceEx(str, fl, pdv);
2210 }