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