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