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