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