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