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