janitorial: Remove remaining NULL checks before free() (found by Smatch).
[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( (const LOGFONTW *)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( (const LOGFONTW *)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((const TEXTMETRICW *)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 (! 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         /* check if the string offsets really fit into the provided size */
1488         /* FIXME: should we check string length as well? */
1489         if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1490             lpOTM->otmpFamilyName = 0; /* doesn't fit */
1491
1492         if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1493             lpOTM->otmpFaceName = 0; /* doesn't fit */
1494
1495         if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1496             lpOTM->otmpStyleName = 0; /* doesn't fit */
1497
1498         if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1499             lpOTM->otmpFullName = 0; /* doesn't fit */
1500     }
1501
1502 end:
1503     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1504         HeapFree(GetProcessHeap(), 0, lpOTMW);
1505
1506     return ret;
1507 }
1508
1509
1510 /***********************************************************************
1511  *           GetOutlineTextMetricsW [GDI32.@]
1512  */
1513 UINT WINAPI GetOutlineTextMetricsW(
1514     HDC hdc,    /* [in]  Handle of device context */
1515     UINT cbData, /* [in]  Size of metric data array */
1516     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1517 {
1518     DC *dc = DC_GetDCPtr( hdc );
1519     OUTLINETEXTMETRICW *output = lpOTM;
1520     UINT ret;
1521
1522     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1523     if(!dc) return 0;
1524
1525     if(dc->gdiFont) {
1526         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1527         if(lpOTM && ret) {
1528             if(ret > cbData) {
1529                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1530                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1531             }
1532
1533 #define WDPTOLP(x) ((x<0)?                                      \
1534                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1535                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1536 #define HDPTOLP(y) ((y<0)?                                      \
1537                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1538                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1539
1540             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1541             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1542             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1543             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1544             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1545             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1546             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1547             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1548             output->otmAscent = HDPTOLP(output->otmAscent);
1549             output->otmDescent = HDPTOLP(output->otmDescent);
1550             output->otmLineGap = HDPTOLP(output->otmLineGap);
1551             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1552             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1553             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1554             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1555             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1556             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1557             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1558             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1559             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1560             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1561             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1562             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1563             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1564             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1565             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1566             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1567             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1568             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1569             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1570             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1571             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1572 #undef WDPTOLP
1573 #undef HDPTOLP
1574             if(output != lpOTM) {
1575                 memcpy(lpOTM, output, cbData);
1576                 HeapFree(GetProcessHeap(), 0, output);
1577                 ret = cbData;
1578             }
1579         }
1580     }
1581
1582     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1583               but really this should just be a return 0. */
1584
1585         ret = sizeof(*lpOTM);
1586         if (lpOTM) {
1587             if(cbData < ret)
1588                 ret = 0;
1589             else {
1590                 memset(lpOTM, 0, ret);
1591                 lpOTM->otmSize = sizeof(*lpOTM);
1592                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1593                 /*
1594                   Further fill of the structure not implemented,
1595                   Needs real values for the structure members
1596                 */
1597             }
1598         }
1599     }
1600     GDI_ReleaseObj(hdc);
1601     return ret;
1602 }
1603
1604
1605 /***********************************************************************
1606  *           GetCharWidthW      (GDI32.@)
1607  *           GetCharWidth32W    (GDI32.@)
1608  */
1609 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1610                                LPINT buffer )
1611 {
1612     UINT i;
1613     BOOL ret = FALSE;
1614     DC * dc = DC_GetDCPtr( hdc );
1615     if (!dc) return FALSE;
1616
1617     if (dc->gdiFont)
1618         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1619     else if (dc->funcs->pGetCharWidth)
1620         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1621
1622     if (ret)
1623     {
1624         /* convert device units to logical */
1625         for( i = firstChar; i <= lastChar; i++, buffer++ )
1626             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1627         ret = TRUE;
1628     }
1629     GDI_ReleaseObj( hdc );
1630     return ret;
1631 }
1632
1633
1634 /***********************************************************************
1635  *           GetCharWidthA      (GDI32.@)
1636  *           GetCharWidth32A    (GDI32.@)
1637  */
1638 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1639                                LPINT buffer )
1640 {
1641     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1642     LPSTR str;
1643     LPWSTR wstr;
1644     BOOL ret = TRUE;
1645
1646     if(count <= 0) return FALSE;
1647
1648     str = HeapAlloc(GetProcessHeap(), 0, count);
1649     for(i = 0; i < count; i++)
1650         str[i] = (BYTE)(firstChar + i);
1651
1652     wstr = FONT_mbtowc(str, count, &wlen);
1653
1654     for(i = 0; i < wlen; i++)
1655     {
1656         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1657         {
1658             ret = FALSE;
1659             break;
1660         }
1661         buffer++;
1662     }
1663
1664     HeapFree(GetProcessHeap(), 0, str);
1665     HeapFree(GetProcessHeap(), 0, wstr);
1666
1667     return ret;
1668 }
1669
1670
1671 /***********************************************************************
1672  *           ExtTextOutA    (GDI32.@)
1673  *
1674  * See ExtTextOutW.
1675  */
1676 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1677                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1678 {
1679     INT wlen;
1680     LPWSTR p;
1681     BOOL ret;
1682     LPINT lpDxW = NULL;
1683
1684     if (flags & ETO_GLYPH_INDEX)
1685         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1686
1687     p = FONT_mbtowc(str, count, &wlen);
1688
1689     if (lpDx) {
1690         unsigned int i = 0, j = 0;
1691
1692         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1693         while(i < count) {
1694             if(IsDBCSLeadByte(str[i])) {
1695                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1696                 i = i + 2;
1697             } else {
1698                 lpDxW[j++] = lpDx[i];
1699                 i = i + 1;
1700             }
1701         }
1702     }
1703
1704     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1705
1706     HeapFree( GetProcessHeap(), 0, p );
1707     HeapFree( GetProcessHeap(), 0, lpDxW );
1708     return ret;
1709 }
1710
1711
1712 /***********************************************************************
1713  *           ExtTextOutW    (GDI32.@)
1714  *
1715  * Draws text using the currently selected font, background color, and text color.
1716  * 
1717  * 
1718  * PARAMS
1719  *    x,y    [I] coordinates of string
1720  *    flags  [I]
1721  *        ETO_GRAYED - undocumented on MSDN
1722  *        ETO_OPAQUE - use background color for fill the rectangle
1723  *        ETO_CLIPPED - clipping text to the rectangle
1724  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1725  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1726  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1727  *                         Affects BiDi ordering
1728  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1729  *        ETO_PDY - unimplemented
1730  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1731  *                            do not translate numbers into locale representations
1732  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1733  *    lprect [I] dimensions for clipping or/and opaquing
1734  *    str    [I] text string
1735  *    count  [I] number of symbols in string
1736  *    lpDx   [I] optional parameter with distance between drawing characters
1737  *
1738  * RETURNS
1739  *    Success: TRUE
1740  *    Failure: FALSE
1741  */
1742 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1743                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1744 {
1745     BOOL ret = FALSE;
1746     LPWSTR reordered_str = (LPWSTR)str;
1747     WORD *glyphs = NULL;
1748     UINT align = GetTextAlign( hdc );
1749     POINT pt;
1750     TEXTMETRICW tm;
1751     LOGFONTW lf;
1752     double cosEsc, sinEsc;
1753     INT *deltas = NULL, char_extra;
1754     SIZE sz;
1755     RECT rc;
1756     BOOL done_extents = FALSE;
1757     INT width, xwidth = 0, ywidth = 0;
1758     DWORD type;
1759     DC * dc = DC_GetDCUpdate( hdc );
1760
1761     if (!dc) return FALSE;
1762
1763     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1764         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1765
1766     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1767     {
1768         GDI_ReleaseObj( hdc );
1769         return ret;
1770     }
1771
1772     type = GetObjectType(hdc);
1773     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1774     {
1775         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1776         GDI_ReleaseObj( hdc );
1777         return ret;
1778     }
1779
1780     if (!lprect)
1781         flags &= ~ETO_CLIPPED;
1782         
1783     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1784     {
1785         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1786
1787         BIDI_Reorder( str, count, GCP_REORDER,
1788                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1789                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1790                       reordered_str, count, NULL );
1791     
1792         flags |= ETO_IGNORELANGUAGE;
1793     }
1794
1795     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1796           lprect, debugstr_wn(str, count), count, lpDx);
1797
1798     if(flags & ETO_GLYPH_INDEX)
1799         glyphs = reordered_str;
1800
1801     if(lprect)
1802         TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1803               lprect->bottom);
1804     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1805
1806     if(align & TA_UPDATECP)
1807     {
1808         GetCurrentPositionEx( hdc, &pt );
1809         x = pt.x;
1810         y = pt.y;
1811     }
1812
1813     GetTextMetricsW(hdc, &tm);
1814     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1815
1816     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1817         lf.lfEscapement = 0;
1818
1819     if(lf.lfEscapement != 0)
1820     {
1821         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1822         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1823     }
1824     else
1825     {
1826         cosEsc = 1;
1827         sinEsc = 0;
1828     }
1829
1830     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1831     {
1832         if(!lprect)
1833         {
1834             if(flags & ETO_GLYPH_INDEX)
1835                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1836             else
1837                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1838
1839             done_extents = TRUE;
1840             rc.left = x;
1841             rc.top = y;
1842             rc.right = x + sz.cx;
1843             rc.bottom = y + sz.cy;
1844         }
1845         else
1846         {
1847             rc = *lprect;
1848         }
1849
1850         LPtoDP(hdc, (POINT*)&rc, 2);
1851
1852         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1853         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1854     }
1855
1856     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1857         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1858
1859     if(count == 0)
1860     {
1861         ret = TRUE;
1862         goto done;
1863     }
1864
1865     pt.x = x;
1866     pt.y = y;
1867     LPtoDP(hdc, &pt, 1);
1868     x = pt.x;
1869     y = pt.y;
1870
1871     char_extra = GetTextCharacterExtra(hdc);
1872     width = 0;
1873     if(char_extra || dc->breakExtra || lpDx)
1874     {
1875         UINT i;
1876         SIZE tmpsz;
1877         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1878         for(i = 0; i < count; i++)
1879         {
1880             if(lpDx && (flags & ETO_PDY))
1881                 deltas[i] = lpDx[i*2] + char_extra;
1882             else if(lpDx)
1883                 deltas[i] = lpDx[i] + char_extra;
1884             else
1885             {
1886                 if(flags & ETO_GLYPH_INDEX)
1887                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1888                 else
1889                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1890
1891                 deltas[i] = tmpsz.cx;
1892             }
1893             
1894             if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1895             {
1896                 deltas[i] = deltas[i] + dc->breakExtra;
1897             }
1898             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1899             width += deltas[i];
1900         }
1901     }
1902     else
1903     {
1904         if(!done_extents)
1905         {
1906             if(flags & ETO_GLYPH_INDEX)
1907                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1908             else
1909                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1910             done_extents = TRUE;
1911         }
1912         width = INTERNAL_XWSTODS(dc, sz.cx);
1913     }
1914     xwidth = width * cosEsc;
1915     ywidth = width * sinEsc;
1916
1917     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1918     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1919     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1920     {
1921     case TA_LEFT:
1922         if (align & TA_UPDATECP)
1923         {
1924             pt.x = x + xwidth;
1925             pt.y = y - ywidth;
1926             DPtoLP(hdc, &pt, 1);
1927             MoveToEx(hdc, pt.x, pt.y, NULL);
1928         }
1929         break;
1930
1931     case TA_CENTER:
1932         x -= xwidth / 2;
1933         y += ywidth / 2;
1934         break;
1935
1936     case TA_RIGHT:
1937         x -= xwidth;
1938         y += ywidth;
1939         if (align & TA_UPDATECP)
1940         {
1941             pt.x = x;
1942             pt.y = y;
1943             DPtoLP(hdc, &pt, 1);
1944             MoveToEx(hdc, pt.x, pt.y, NULL);
1945         }
1946         break;
1947     }
1948
1949     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1950     {
1951     case TA_TOP:
1952         y += tm.tmAscent * cosEsc;
1953         x += tm.tmAscent * sinEsc;
1954         break;
1955
1956     case TA_BOTTOM:
1957         y -= tm.tmDescent * cosEsc;
1958         x -= tm.tmDescent * sinEsc;
1959         break;
1960
1961     case TA_BASELINE:
1962         break;
1963     }
1964
1965     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1966     {
1967         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1968         {
1969             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1970                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1971             {
1972                 RECT rc;
1973                 rc.left = x;
1974                 rc.right = x + width;
1975                 rc.top = y - tm.tmAscent;
1976                 rc.bottom = y + tm.tmDescent;
1977                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1978             }
1979         }
1980     }
1981
1982     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1983     {
1984         HFONT orig_font = dc->hFont, cur_font;
1985         UINT glyph;
1986         INT span = 0, *offsets = NULL, i;
1987
1988         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1989         for(i = 0; i < count; i++)
1990         {
1991             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1992             if(cur_font != dc->hFont)
1993             {
1994                 if(!offsets)
1995                 {
1996                     int j;
1997                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1998                     offsets[0] = 0;
1999                     if(!deltas)
2000                     {
2001                         SIZE tmpsz;
2002                         for(j = 1; j < count; j++)
2003                         {
2004                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2005                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2006                         }
2007                     }
2008                     else
2009                     {
2010                         for(j = 1; j < count; j++)
2011                             offsets[j] = offsets[j-1] + deltas[j];
2012                     }
2013                 }
2014                 if(span)
2015                 {
2016                     if (PATH_IsPathOpen(dc->path))
2017                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2018                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2019                                               glyphs, span, deltas ? deltas + i - span : NULL);
2020                     else
2021                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2022                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2023                                            glyphs, span, deltas ? deltas + i - span : NULL);
2024                     span = 0;
2025                 }
2026                 SelectObject(hdc, cur_font);
2027             }
2028             glyphs[span++] = glyph;
2029
2030             if(i == count - 1)
2031             {
2032                 if (PATH_IsPathOpen(dc->path))
2033                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2034                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
2035                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2036                                           glyphs, span, deltas ? deltas + count - span : NULL);
2037                 else
2038                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2039                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
2040                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2041                                              glyphs, span, deltas ? deltas + count - span : NULL);
2042                 SelectObject(hdc, orig_font);
2043                 HeapFree(GetProcessHeap(), 0, offsets);
2044            }
2045         }
2046     }
2047     else
2048     {
2049         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2050         {
2051             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2052             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2053             flags |= ETO_GLYPH_INDEX;
2054         }
2055
2056         if (PATH_IsPathOpen(dc->path))
2057             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2058                                   glyphs ? glyphs : reordered_str, count, deltas);
2059         else
2060             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2061                                      glyphs ? glyphs : reordered_str, count, deltas);
2062     }
2063
2064 done:
2065     HeapFree(GetProcessHeap(), 0, deltas);
2066     if(glyphs != reordered_str)
2067         HeapFree(GetProcessHeap(), 0, glyphs);
2068     if(reordered_str != str)
2069         HeapFree(GetProcessHeap(), 0, reordered_str);
2070
2071     GDI_ReleaseObj( hdc );
2072
2073     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2074     {
2075         int underlinePos, strikeoutPos;
2076         int underlineWidth, strikeoutWidth;
2077         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2078         OUTLINETEXTMETRICW* otm = NULL;
2079
2080         if(!size)
2081         {
2082             underlinePos = 0;
2083             underlineWidth = tm.tmAscent / 20 + 1;
2084             strikeoutPos = tm.tmAscent / 2;
2085             strikeoutWidth = underlineWidth;
2086         }
2087         else
2088         {
2089             otm = HeapAlloc(GetProcessHeap(), 0, size);
2090             GetOutlineTextMetricsW(hdc, size, otm);
2091             underlinePos = otm->otmsUnderscorePosition;
2092             underlineWidth = otm->otmsUnderscoreSize;
2093             strikeoutPos = otm->otmsStrikeoutPosition;
2094             strikeoutWidth = otm->otmsStrikeoutSize;
2095             HeapFree(GetProcessHeap(), 0, otm);
2096         }
2097
2098         if (PATH_IsPathOpen(dc->path))
2099         {
2100             POINT pts[5];
2101             HPEN hpen;
2102             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2103
2104             hbrush = SelectObject(hdc, hbrush);
2105             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2106
2107             if (lf.lfUnderline)
2108             {
2109                 pts[0].x = x - underlinePos * sinEsc;
2110                 pts[0].y = y - underlinePos * cosEsc;
2111                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2112                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2113                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2114                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2115                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2116                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2117                 pts[4].x = pts[0].x;
2118                 pts[4].y = pts[0].y;
2119                 DPtoLP(hdc, pts, 5);
2120                 Polygon(hdc, pts, 5);
2121             }
2122
2123             if (lf.lfStrikeOut)
2124             {
2125                 pts[0].x = x - strikeoutPos * sinEsc;
2126                 pts[0].y = y - strikeoutPos * cosEsc;
2127                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2128                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2129                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2130                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2131                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2132                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2133                 pts[4].x = pts[0].x;
2134                 pts[4].y = pts[0].y;
2135                 DPtoLP(hdc, pts, 5);
2136                 Polygon(hdc, pts, 5);
2137             }
2138
2139             SelectObject(hdc, hpen);
2140             hbrush = SelectObject(hdc, hbrush);
2141             DeleteObject(hbrush);
2142         }
2143         else
2144         {
2145             POINT pts[2], oldpt;
2146             HPEN hpen;
2147
2148             if (lf.lfUnderline)
2149             {
2150                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2151                 hpen = SelectObject(hdc, hpen);
2152                 pts[0].x = x;
2153                 pts[0].y = y;
2154                 pts[1].x = x + xwidth;
2155                 pts[1].y = y - ywidth;
2156                 DPtoLP(hdc, pts, 2);
2157                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2158                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2159                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2160                 DeleteObject(SelectObject(hdc, hpen));
2161             }
2162
2163             if (lf.lfStrikeOut)
2164             {
2165                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2166                 hpen = SelectObject(hdc, hpen);
2167                 pts[0].x = x;
2168                 pts[0].y = y;
2169                 pts[1].x = x + xwidth;
2170                 pts[1].y = y - ywidth;
2171                 DPtoLP(hdc, pts, 2);
2172                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2173                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2174                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2175                 DeleteObject(SelectObject(hdc, hpen));
2176             }
2177         }
2178     }
2179
2180     return ret;
2181 }
2182
2183
2184 /***********************************************************************
2185  *           TextOutA    (GDI32.@)
2186  */
2187 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2188 {
2189     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2190 }
2191
2192
2193 /***********************************************************************
2194  *           TextOutW    (GDI32.@)
2195  */
2196 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2197 {
2198     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2199 }
2200
2201
2202 /***********************************************************************
2203  *              PolyTextOutA (GDI32.@)
2204  *
2205  * See PolyTextOutW.
2206  */
2207 BOOL WINAPI PolyTextOutA ( HDC hdc,               /* [in] Handle to device context */
2208                            PPOLYTEXTA pptxt,      /* [in] Array of strings */
2209                            INT cStrings )         /* [in] Number of strings in array */
2210 {
2211     for (; cStrings>0; cStrings--, pptxt++)
2212         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2213             return FALSE;
2214     return TRUE;
2215 }
2216
2217
2218
2219 /***********************************************************************
2220  *              PolyTextOutW (GDI32.@)
2221  *
2222  * Draw several Strings
2223  *
2224  * RETURNS
2225  *  TRUE:  Success.
2226  *  FALSE: Failure.
2227  */
2228 BOOL WINAPI PolyTextOutW ( HDC hdc,               /* [in] Handle to device context */
2229                            PPOLYTEXTW pptxt,      /* [in] Array of strings */
2230                            INT cStrings )         /* [in] Number of strings in array */
2231 {
2232     for (; cStrings>0; cStrings--, pptxt++)
2233         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2234             return FALSE;
2235     return TRUE;
2236 }
2237
2238
2239 /* FIXME: all following APIs ******************************************/
2240
2241
2242 /***********************************************************************
2243  *           SetMapperFlags    (GDI32.@)
2244  */
2245 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2246 {
2247     DC *dc = DC_GetDCPtr( hDC );
2248     DWORD ret = 0;
2249     if(!dc) return 0;
2250     if(dc->funcs->pSetMapperFlags)
2251     {
2252         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2253         /* FIXME: ret is just a success flag, we should return a proper value */
2254     }
2255     else
2256         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2257     GDI_ReleaseObj( hDC );
2258     return ret;
2259 }
2260
2261 /***********************************************************************
2262  *          GetAspectRatioFilterEx  (GDI.486)
2263  */
2264 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2265 {
2266   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2267   return FALSE;
2268 }
2269
2270 /***********************************************************************
2271  *          GetAspectRatioFilterEx  (GDI32.@)
2272  */
2273 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2274 {
2275   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2276   return FALSE;
2277 }
2278
2279
2280 /***********************************************************************
2281  *           GetCharABCWidthsA   (GDI32.@)
2282  *
2283  * See GetCharABCWidthsW.
2284  */
2285 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2286                                   LPABC abc )
2287 {
2288     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2289     LPSTR str;
2290     LPWSTR wstr;
2291     BOOL ret = TRUE;
2292
2293     if(count <= 0) return FALSE;
2294
2295     str = HeapAlloc(GetProcessHeap(), 0, count);
2296     for(i = 0; i < count; i++)
2297         str[i] = (BYTE)(firstChar + i);
2298
2299     wstr = FONT_mbtowc(str, count, &wlen);
2300
2301     for(i = 0; i < wlen; i++)
2302     {
2303         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2304         {
2305             ret = FALSE;
2306             break;
2307         }
2308         abc++;
2309     }
2310
2311     HeapFree(GetProcessHeap(), 0, str);
2312     HeapFree(GetProcessHeap(), 0, wstr);
2313
2314     return ret;
2315 }
2316
2317
2318 /******************************************************************************
2319  * GetCharABCWidthsW [GDI32.@]
2320  *
2321  * Retrieves widths of characters in range.
2322  *
2323  * PARAMS
2324  *    hdc       [I] Handle of device context
2325  *    firstChar [I] First character in range to query
2326  *    lastChar  [I] Last character in range to query
2327  *    abc       [O] Address of character-width structure
2328  *
2329  * NOTES
2330  *    Only works with TrueType fonts
2331  *
2332  * RETURNS
2333  *    Success: TRUE
2334  *    Failure: FALSE
2335  */
2336 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2337                                    LPABC abc )
2338 {
2339     DC *dc = DC_GetDCPtr(hdc);
2340     unsigned int i;
2341     BOOL ret = FALSE;
2342
2343     if (!dc) return FALSE;
2344
2345     if(dc->gdiFont)
2346         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2347     else
2348         FIXME(": stub\n");
2349
2350     if (ret)
2351     {
2352         /* convert device units to logical */
2353         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2354             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2355             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2356             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2357         }
2358         ret = TRUE;
2359     }
2360
2361     GDI_ReleaseObj(hdc);
2362     return ret;
2363 }
2364
2365
2366 /******************************************************************************
2367  * GetCharABCWidthsI [GDI32.@]
2368  *
2369  * Retrieves widths of characters in range.
2370  *
2371  * PARAMS
2372  *    hdc       [I] Handle of device context
2373  *    firstChar [I] First glyphs in range to query
2374  *    count     [I] Last glyphs in range to query
2375  *    pgi       [i] Array of glyphs to query
2376  *    abc       [O] Address of character-width structure
2377  *
2378  * NOTES
2379  *    Only works with TrueType fonts
2380  *
2381  * RETURNS
2382  *    Success: TRUE
2383  *    Failure: FALSE
2384  */
2385 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2386                                LPWORD pgi, LPABC abc)
2387 {
2388     DC *dc = DC_GetDCPtr(hdc);
2389     unsigned int i;
2390     BOOL ret = FALSE;
2391
2392     if (!dc) return FALSE;
2393
2394     if(dc->gdiFont)
2395         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2396     else
2397         FIXME(": stub\n");
2398
2399     if (ret)
2400     {
2401         /* convert device units to logical */
2402         for( i = 0; i < count; i++, abc++ ) {
2403             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2404             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2405             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2406         }
2407         ret = TRUE;
2408     }
2409
2410     GDI_ReleaseObj(hdc);
2411     return ret;
2412 }
2413
2414
2415 /***********************************************************************
2416  *           GetGlyphOutlineA    (GDI32.@)
2417  */
2418 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2419                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2420                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2421 {
2422     LPWSTR p = NULL;
2423     DWORD ret;
2424     UINT c;
2425
2426     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2427         int len;
2428         char mbchs[2];
2429         if(uChar > 0xff) { /* but, 2 bytes character only */
2430             len = 2;
2431             mbchs[0] = (uChar & 0xff00) >> 8;
2432             mbchs[1] = (uChar & 0xff);
2433         } else {
2434             len = 1;
2435             mbchs[0] = (uChar & 0xff);
2436         }
2437         p = FONT_mbtowc(mbchs, len, NULL);
2438         c = p[0];
2439     } else
2440         c = uChar;
2441     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2442                            lpmat2);
2443     HeapFree(GetProcessHeap(), 0, p);
2444     return ret;
2445 }
2446
2447 /***********************************************************************
2448  *           GetGlyphOutlineW    (GDI32.@)
2449  */
2450 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2451                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2452                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2453 {
2454     DC *dc = DC_GetDCPtr(hdc);
2455     DWORD ret;
2456
2457     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2458           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2459
2460     if(!dc) return GDI_ERROR;
2461
2462     if(dc->gdiFont)
2463       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2464                                    cbBuffer, lpBuffer, lpmat2);
2465     else
2466       ret = GDI_ERROR;
2467
2468     GDI_ReleaseObj(hdc);
2469     return ret;
2470 }
2471
2472
2473 /***********************************************************************
2474  *           CreateScalableFontResourceA   (GDI32.@)
2475  */
2476 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2477                                              LPCSTR lpszResourceFile,
2478                                              LPCSTR lpszFontFile,
2479                                              LPCSTR lpszCurrentPath )
2480 {
2481     HANDLE f;
2482
2483     /* fHidden=1 - only visible for the calling app, read-only, not
2484      * enumbered with EnumFonts/EnumFontFamilies
2485      * lpszCurrentPath can be NULL
2486      */
2487     FIXME("(%ld,%s,%s,%s): stub\n",
2488           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2489           debugstr_a(lpszCurrentPath) );
2490
2491     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2492     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2493         CloseHandle(f);
2494         SetLastError(ERROR_FILE_EXISTS);
2495         return FALSE;
2496     }
2497     return FALSE; /* create failed */
2498 }
2499
2500 /***********************************************************************
2501  *           CreateScalableFontResourceW   (GDI32.@)
2502  */
2503 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2504                                              LPCWSTR lpszResourceFile,
2505                                              LPCWSTR lpszFontFile,
2506                                              LPCWSTR lpszCurrentPath )
2507 {
2508     FIXME("(%ld,%p,%p,%p): stub\n",
2509           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2510     return FALSE; /* create failed */
2511 }
2512
2513 /*************************************************************************
2514  *             GetKerningPairsA   (GDI32.@)
2515  */
2516 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2517                                LPKERNINGPAIR kern_pairA )
2518 {
2519     INT charset;
2520     CHARSETINFO csi;
2521     CPINFO cpi;
2522     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2523     KERNINGPAIR *kern_pairW;
2524
2525     if (!cPairs && kern_pairA)
2526     {
2527         SetLastError(ERROR_INVALID_PARAMETER);
2528         return 0;
2529     }
2530
2531     charset = GetTextCharset(hDC);
2532     if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2533     {
2534         FIXME("Can't find codepage for charset %d\n", charset);
2535         return 0;
2536     }
2537     if (!GetCPInfo(csi.ciACP, &cpi))
2538     {
2539         FIXME("Can't find codepage %u info\n", csi.ciACP);
2540         return 0;
2541     }
2542     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2543
2544     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2545     if (!total_kern_pairs) return 0;
2546
2547     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2548     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2549
2550     for (i = 0; i < total_kern_pairs; i++)
2551     {
2552         char first, second;
2553
2554         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2555             continue;
2556
2557         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2558             continue;
2559
2560         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2561             continue;
2562
2563         if (kern_pairA)
2564         {
2565             if (kern_pairs_copied >= cPairs) break;
2566
2567             kern_pairA->wFirst = (BYTE)first;
2568             kern_pairA->wSecond = (BYTE)second;
2569             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2570             kern_pairA++;
2571         }
2572         kern_pairs_copied++;
2573     }
2574
2575     HeapFree(GetProcessHeap(), 0, kern_pairW);
2576
2577     return kern_pairs_copied;
2578 }
2579
2580 /*************************************************************************
2581  *             GetKerningPairsW   (GDI32.@)
2582  */
2583 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2584                                  LPKERNINGPAIR lpKerningPairs )
2585 {
2586     DC *dc;
2587     DWORD ret = 0;
2588
2589     TRACE("(%p,%ld,%p)\n", hDC, cPairs, lpKerningPairs);
2590
2591     if (!cPairs && lpKerningPairs)
2592     {
2593         SetLastError(ERROR_INVALID_PARAMETER);
2594         return 0;
2595     }
2596
2597     dc = DC_GetDCPtr(hDC);
2598     if (!dc) return 0;
2599
2600     if (dc->gdiFont)
2601         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2602
2603     GDI_ReleaseObj(hDC);
2604     return ret;
2605 }
2606
2607 /*************************************************************************
2608  * TranslateCharsetInfo [GDI32.@]
2609  *
2610  * Fills a CHARSETINFO structure for a character set, code page, or
2611  * font. This allows making the correspondance between different labelings
2612  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2613  * of the same encoding.
2614  *
2615  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2616  * only one codepage should be set in *lpSrc.
2617  *
2618  * RETURNS
2619  *   TRUE on success, FALSE on failure.
2620  *
2621  */
2622 BOOL WINAPI TranslateCharsetInfo(
2623   LPDWORD lpSrc, /* [in]
2624        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2625        if flags == TCI_SRCCHARSET: a character set value
2626        if flags == TCI_SRCCODEPAGE: a code page value
2627                  */
2628   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2629   DWORD flags /* [in] determines interpretation of lpSrc */)
2630 {
2631     int index = 0;
2632     switch (flags) {
2633     case TCI_SRCFONTSIG:
2634         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2635       break;
2636     case TCI_SRCCODEPAGE:
2637       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2638       break;
2639     case TCI_SRCCHARSET:
2640       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2641       break;
2642     default:
2643       return FALSE;
2644     }
2645     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2646     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2647     return TRUE;
2648 }
2649
2650 /*************************************************************************
2651  *             GetFontLanguageInfo   (GDI32.@)
2652  */
2653 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2654 {
2655         FONTSIGNATURE fontsig;
2656         static const DWORD GCP_DBCS_MASK=0x003F0000,
2657                 GCP_DIACRITIC_MASK=0x00000000,
2658                 FLI_GLYPHS_MASK=0x00000000,
2659                 GCP_GLYPHSHAPE_MASK=0x00000040,
2660                 GCP_KASHIDA_MASK=0x00000000,
2661                 GCP_LIGATE_MASK=0x00000000,
2662                 GCP_USEKERNING_MASK=0x00000000,
2663                 GCP_REORDER_MASK=0x00000060;
2664
2665         DWORD result=0;
2666
2667         GetTextCharsetInfo( hdc, &fontsig, 0 );
2668         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2669
2670         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2671                 result|=GCP_DBCS;
2672
2673         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2674                 result|=GCP_DIACRITIC;
2675
2676         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2677                 result|=FLI_GLYPHS;
2678
2679         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2680                 result|=GCP_GLYPHSHAPE;
2681
2682         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2683                 result|=GCP_KASHIDA;
2684
2685         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2686                 result|=GCP_LIGATE;
2687
2688         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2689                 result|=GCP_USEKERNING;
2690
2691         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2692         if( GetTextAlign( hdc) & TA_RTLREADING )
2693             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2694                     result|=GCP_REORDER;
2695
2696         return result;
2697 }
2698
2699
2700 /*************************************************************************
2701  * GetFontData [GDI32.@]
2702  *
2703  * Retrieve data for TrueType font.
2704  *
2705  * RETURNS
2706  *
2707  * success: Number of bytes returned
2708  * failure: GDI_ERROR
2709  *
2710  * NOTES
2711  *
2712  * Calls SetLastError()
2713  *
2714  */
2715 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2716     LPVOID buffer, DWORD length)
2717 {
2718     DC *dc = DC_GetDCPtr(hdc);
2719     DWORD ret = GDI_ERROR;
2720
2721     if(!dc) return GDI_ERROR;
2722
2723     if(dc->gdiFont)
2724       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2725
2726     GDI_ReleaseObj(hdc);
2727     return ret;
2728 }
2729
2730 /*************************************************************************
2731  * GetGlyphIndicesA [GDI32.@]
2732  */
2733 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2734                               LPWORD pgi, DWORD flags)
2735 {
2736     DWORD ret;
2737     WCHAR *lpstrW;
2738     INT countW;
2739
2740     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2741           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2742
2743     lpstrW = FONT_mbtowc(lpstr, count, &countW);
2744     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2745     HeapFree(GetProcessHeap(), 0, lpstrW);
2746
2747     return ret;
2748 }
2749
2750 /*************************************************************************
2751  * GetGlyphIndicesW [GDI32.@]
2752  */
2753 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2754                               LPWORD pgi, DWORD flags)
2755 {
2756     DC *dc = DC_GetDCPtr(hdc);
2757     DWORD ret = GDI_ERROR;
2758
2759     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2760           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2761
2762     if(!dc) return GDI_ERROR;
2763
2764     if(dc->gdiFont)
2765         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2766
2767     GDI_ReleaseObj(hdc);
2768     return ret;
2769 }
2770
2771 /*************************************************************************
2772  * GetCharacterPlacementA [GDI32.@]
2773  *
2774  * See GetCharacterPlacementW.
2775  *
2776  * NOTES:
2777  *  the web browser control of ie4 calls this with dwFlags=0
2778  */
2779 DWORD WINAPI
2780 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2781                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2782                          DWORD dwFlags)
2783 {
2784     WCHAR *lpStringW;
2785     INT uCountW;
2786     GCP_RESULTSW resultsW;
2787     DWORD ret;
2788
2789     TRACE("%s, %d, %d, 0x%08lx\n",
2790           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2791
2792     /* both structs are equal in size */
2793     memcpy(&resultsW, lpResults, sizeof(resultsW));
2794
2795     lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
2796     if(lpResults->lpOutString)
2797         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2798
2799     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2800
2801     lpResults->nGlyphs = resultsW.nGlyphs;
2802     lpResults->nMaxFit = resultsW.nMaxFit;
2803
2804     if(lpResults->lpOutString) {
2805         WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
2806                             lpResults->lpOutString, uCount, NULL, NULL );
2807     }
2808
2809     HeapFree(GetProcessHeap(), 0, lpStringW);
2810     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2811
2812     return ret;
2813 }
2814
2815 /*************************************************************************
2816  * GetCharacterPlacementW [GDI32.@]
2817  *
2818  *   Retrieve information about a string. This includes the width, reordering,
2819  *   Glyphing and so on.
2820  *
2821  * RETURNS
2822  *
2823  *   The width and height of the string if successful, 0 if failed.
2824  *
2825  * BUGS
2826  *
2827  *   All flags except GCP_REORDER are not yet implemented.
2828  *   Reordering is not 100% complient to the Windows BiDi method.
2829  *   Caret positioning is not yet implemented for BiDi.
2830  *   Classes are not yet implemented.
2831  *
2832  */
2833 DWORD WINAPI
2834 GetCharacterPlacementW(
2835                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2836                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2837                 INT uCount,             /* [in] Number of WORDS in string. */
2838                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2839                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2840                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2841                 )
2842 {
2843     DWORD ret=0;
2844     SIZE size;
2845     UINT i, nSet;
2846
2847     TRACE("%s, %d, %d, 0x%08lx\n",
2848           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2849
2850     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2851           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2852             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2853             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2854             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2855
2856     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2857     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2858     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2859         FIXME("Caret positions for complex scripts not implemented\n");
2860
2861         nSet = (UINT)uCount;
2862         if(nSet > lpResults->nGlyphs)
2863                 nSet = lpResults->nGlyphs;
2864
2865         /* return number of initialized fields */
2866         lpResults->nGlyphs = nSet;
2867
2868         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2869         {
2870                 /* Treat the case where no special handling was requested in a fastpath way */
2871                 /* copy will do if the GCP_REORDER flag is not set */
2872                 if(lpResults->lpOutString)
2873                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2874
2875                 if(lpResults->lpOrder)
2876                 {
2877                         for(i = 0; i < nSet; i++)
2878                                 lpResults->lpOrder[i] = i;
2879                 }
2880         } else
2881         {
2882             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2883                           nSet, lpResults->lpOrder );
2884         }
2885
2886         /* FIXME: Will use the placement chars */
2887         if (lpResults->lpDx)
2888         {
2889                 int c;
2890                 for (i = 0; i < nSet; i++)
2891                 {
2892                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2893                                 lpResults->lpDx[i]= c;
2894                 }
2895         }
2896
2897     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2898     {
2899         int pos = 0;
2900        
2901         lpResults->lpCaretPos[0] = 0;
2902         for (i = 1; i < nSet; i++)
2903             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2904                 lpResults->lpCaretPos[i] = (pos += size.cx);
2905     }
2906    
2907     if(lpResults->lpGlyphs)
2908         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2909
2910     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2911       ret = MAKELONG(size.cx, size.cy);
2912
2913     return ret;
2914 }
2915
2916 /*************************************************************************
2917  *      GetCharABCWidthsFloatA [GDI32.@]
2918  *
2919  * See GetCharABCWidthsFloatW.
2920  */
2921 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2922 {
2923     INT i, wlen, count = (INT)(last - first + 1);
2924     LPSTR str;
2925     LPWSTR wstr;
2926     BOOL ret = TRUE;
2927
2928     if (count <= 0) return FALSE;
2929
2930     str = HeapAlloc(GetProcessHeap(), 0, count);
2931
2932     for(i = 0; i < count; i++)
2933         str[i] = (BYTE)(first + i);
2934
2935     wstr = FONT_mbtowc(str, count, &wlen);
2936
2937     for (i = 0; i < wlen; i++)
2938     {
2939         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2940         {
2941             ret = FALSE;
2942             break;
2943         }
2944         abcf++;
2945     }
2946
2947     HeapFree( GetProcessHeap(), 0, str );
2948     HeapFree( GetProcessHeap(), 0, wstr );
2949
2950     return ret;
2951 }
2952
2953 /*************************************************************************
2954  *      GetCharABCWidthsFloatW [GDI32.@]
2955  *
2956  * Retrieves widths of a range of characters.
2957  *
2958  * PARAMS
2959  *    hdc   [I] Handle to device context.
2960  *    first [I] First character in range to query.
2961  *    last  [I] Last character in range to query.
2962  *    abcf  [O] Array of LPABCFLOAT structures.
2963  *
2964  * RETURNS
2965  *    Success: TRUE
2966  *    Failure: FALSE
2967  *
2968  * BUGS
2969  *    Only works with TrueType fonts. It also doesn't return real
2970  *    floats but converted integers because it's implemented on
2971  *    top of GetCharABCWidthsW.
2972  */
2973 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2974 {
2975     ABC *abc;
2976     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2977     BOOL ret;
2978
2979     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2980
2981     abc = HeapAlloc( GetProcessHeap(), 0, size );
2982     if (!abc) return FALSE;
2983
2984     ret = GetCharABCWidthsW( hdc, first, last, abc );
2985     if (ret)
2986     {
2987         for (i = first; i <= last; i++, abc++, abcf++)
2988         {
2989             abcf->abcfA = abc->abcA;
2990             abcf->abcfB = abc->abcB;
2991             abcf->abcfC = abc->abcC;
2992         }
2993     }
2994     HeapFree( GetProcessHeap(), 0, abc );
2995     return ret;
2996 }
2997
2998 /*************************************************************************
2999  *      GetCharWidthFloatA [GDI32.@]
3000  */
3001 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3002                                     UINT iLastChar, PFLOAT pxBuffer)
3003 {
3004        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
3005        return 0;
3006 }
3007
3008 /*************************************************************************
3009  *      GetCharWidthFloatW [GDI32.@]
3010  */
3011 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3012                                     UINT iLastChar, PFLOAT pxBuffer)
3013 {
3014        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
3015        return 0;
3016 }
3017
3018
3019 /***********************************************************************
3020  *                                                                     *
3021  *           Font Resource API                                         *
3022  *                                                                     *
3023  ***********************************************************************/
3024
3025 /***********************************************************************
3026  *           AddFontResourceA    (GDI32.@)
3027  */
3028 INT WINAPI AddFontResourceA( LPCSTR str )
3029 {
3030     return AddFontResourceExA( str, 0, NULL);
3031 }
3032
3033 /***********************************************************************
3034  *           AddFontResourceW    (GDI32.@)
3035  */
3036 INT WINAPI AddFontResourceW( LPCWSTR str )
3037 {
3038     return AddFontResourceExW(str, 0, NULL);
3039 }
3040
3041
3042 /***********************************************************************
3043  *           AddFontResourceExA    (GDI32.@)
3044  */
3045 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3046 {
3047     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3048     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3049     INT ret;
3050
3051     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3052     ret = AddFontResourceExW(strW, fl, pdv);
3053     HeapFree(GetProcessHeap(), 0, strW);
3054     return ret;
3055 }
3056
3057 /***********************************************************************
3058  *           AddFontResourceExW    (GDI32.@)
3059  */
3060 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3061 {
3062     return WineEngAddFontResourceEx(str, fl, pdv);
3063 }
3064
3065 /***********************************************************************
3066  *           RemoveFontResourceA    (GDI32.@)
3067  */
3068 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3069 {
3070     return RemoveFontResourceExA(str, 0, 0);
3071 }
3072
3073 /***********************************************************************
3074  *           RemoveFontResourceW    (GDI32.@)
3075  */
3076 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3077 {
3078     return RemoveFontResourceExW(str, 0, 0);
3079 }
3080
3081 /***********************************************************************
3082  *           AddFontMemResourceEx    (GDI32.@)
3083  */
3084 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3085 {
3086     FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3087     return NULL;
3088 }
3089
3090 /***********************************************************************
3091  *           RemoveFontResourceExA    (GDI32.@)
3092  */
3093 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3094 {
3095     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3096     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3097     INT ret;
3098
3099     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3100     ret = RemoveFontResourceExW(strW, fl, pdv);
3101     HeapFree(GetProcessHeap(), 0, strW);
3102     return ret;
3103 }
3104
3105 /***********************************************************************
3106  *           RemoveFontResourceExW    (GDI32.@)
3107  */
3108 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3109 {
3110     return WineEngRemoveFontResourceEx(str, fl, pdv);
3111 }
3112
3113 /***********************************************************************
3114  *           GetTextCharset    (GDI32.@)
3115  */
3116 UINT WINAPI GetTextCharset(HDC hdc)
3117 {
3118     /* MSDN docs say this is equivalent */
3119     return GetTextCharsetInfo(hdc, NULL, 0);
3120 }
3121
3122 /***********************************************************************
3123  *           GetTextCharsetInfo    (GDI32.@)
3124  */
3125 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3126 {
3127     UINT ret = DEFAULT_CHARSET;
3128     DC *dc = DC_GetDCPtr(hdc);
3129
3130     if (!dc) goto done;
3131
3132     if (dc->gdiFont)
3133         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3134
3135     GDI_ReleaseObj(hdc);
3136
3137 done:
3138     if (ret == DEFAULT_CHARSET && fs)
3139         memset(fs, 0, sizeof(FONTSIGNATURE));
3140     return ret;
3141 }
3142
3143 /***********************************************************************
3144  *           GdiGetCharDimensions    (GDI32.@)
3145  *
3146  * Gets the average width of the characters in the English alphabet.
3147  *
3148  * PARAMS
3149  *  hdc    [I] Handle to the device context to measure on.
3150  *  lptm   [O] Pointer to memory to store the text metrics into.
3151  *  height [O] On exit, the maximum height of characters in the English alphabet.
3152  *
3153  * RETURNS
3154  *  The average width of characters in the English alphabet.
3155  *
3156  * NOTES
3157  *  This function is used by the dialog manager to get the size of a dialog
3158  *  unit. It should also be used by other pieces of code that need to know
3159  *  the size of a dialog unit in logical units without having access to the
3160  *  window handle of the dialog.
3161  *  Windows caches the font metrics from this function, but we don't and
3162  *  there doesn't appear to be an immediate advantage to do so.
3163  *
3164  * SEE ALSO
3165  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3166  */
3167 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3168 {
3169     SIZE sz;
3170     static const WCHAR alphabet[] = {
3171         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3172         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3173         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3174
3175     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3176
3177     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3178
3179     if (height) *height = sz.cy;
3180     return (sz.cx / 26 + 1) / 2;
3181 }
3182
3183 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3184 {
3185     FIXME("(%d): stub\n", fEnableEUDC);
3186     return FALSE;
3187 }
3188
3189 /***********************************************************************
3190  *           GetCharWidthI    (GDI32.@)
3191  */
3192 BOOL WINAPI GetCharWidthI(HDC hdc, UINT giFirst, UINT cgi, LPWORD pgi, LPINT lpBuffer)
3193 {
3194     FIXME("(%p, %d, %d, %p, %p): stub\n", hdc, giFirst, cgi, pgi, lpBuffer);
3195     return FALSE;
3196 }
3197
3198 /***********************************************************************
3199  *           GetFontUnicodeRanges    (GDI32.@)
3200  */
3201 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3202 {
3203     FIXME("(%p, %p): stub\n", hdc, lpgs);
3204     return 0;
3205 }