Release 970101
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * Enhacements by Juergen Marquardt 1996
7  *
8  * Implementation of a second font cache which 
9  * will be updated dynamically
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <X11/Xatom.h>
16 #include "font.h"
17 #include "heap.h"
18 #include "metafile.h"
19 #include "options.h"
20 #include "xmalloc.h"
21 #include "stddebug.h"
22 #include "debug.h"
23
24 #define FONTCACHE       32      /* dynamic font cache size */
25 #define MAX_FONTS       256
26 static LPLOGFONT16 lpLogFontList[MAX_FONTS+1];
27
28 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
29
30 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
31                              (((cs)->rbearing|(cs)->lbearing| \
32                                (cs)->ascent|(cs)->descent) == 0))
33
34 /* 
35  * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
36  * character.  If the character is in the column and exists, then return the
37  * appropriate metrics (note that fonts with common per-character metrics will
38  * return min_bounds).  If none of these hold true, try again with the default
39  * char.
40  */
41 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
42 { \
43     cs = def; \
44     if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
45         if (fs->per_char == NULL) { \
46             cs = &fs->min_bounds; \
47         } else { \
48             cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
49             if (CI_NONEXISTCHAR(cs)) cs = def; \
50         } \
51     } \
52 }
53
54 #define CI_GET_DEFAULT_INFO(fs,cs) \
55   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
56
57 struct FontStructure {
58         char *window;
59         char *x11;
60 } FontNames[32];
61 int FontSize;
62
63
64 /***********************************************************************
65  *           FONT_Init
66  */
67 BOOL32 FONT_Init( void )
68 {
69   char  temp[1024];
70   LPSTR ptr;
71   int i;
72
73   if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
74   {
75     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
76       if( strcmp( ptr, "default" ) )
77         FontNames[i++].window = xstrdup( ptr );
78     FontSize = i;
79
80     for( i = 1; i < FontSize; i++ )
81     {
82         PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
83                                   temp, sizeof(temp) );
84         FontNames[i].x11 = xstrdup( temp );
85     }
86     PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
87     FontNames[0].x11 = xstrdup( temp );
88
89   } else {
90     FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
91     FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
92     FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
93     FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
94     FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
95     FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
96     FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
97     FontNames[7].window = "system"; FontNames[7].x11 = "*-helvetica";
98     FontSize = 8;
99   }
100   return TRUE;
101 }
102
103 /***********************************************************************
104  *           FONT_ChkX11Family
105  *
106  * returns a valid X11 equivalent if a Windows face name 
107  * is like a X11 family  - or NULL if translation is needed
108  */
109 static char *FONT_ChkX11Family(char *winFaceName )
110 {
111   static char x11fam[32+2];   /* will be returned */
112   int i;
113
114   for(i = 0; lpLogFontList[i] != NULL; i++)
115     if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
116     {
117         strcpy(x11fam,"*-");
118         return strcat(x11fam,winFaceName);
119     }    
120   return NULL;               /* a FONT_TranslateName() call is needed */
121 }
122
123
124
125 /***********************************************************************
126  *           FONT_TranslateName
127  *
128  * Translate a Windows face name to its X11 equivalent.
129  * This will probably have to be customizable.
130  */
131 static const char *FONT_TranslateName( char *winFaceName )
132 {
133   int i;
134
135   for (i = 1; i < FontSize; i ++)
136     if( !lstrcmpi32A( winFaceName, FontNames[i].window ) ) {
137       dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
138       return FontNames[i].x11;
139     }
140   return FontNames[0].x11;
141 }
142
143
144 /***********************************************************************
145  *           FONT_MatchFont
146  *
147  * Find a X font matching the logical font.
148  */
149 static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
150 {
151     char pattern[100];
152     const char *family, *weight, *charset;
153     char **names;
154     char slant, oldspacing, spacing;
155     int width, height, oldheight, count;
156     XFontStruct * fontStruct;
157     
158     dprintf_font(stddeb,
159         "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
160         font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
161     weight = (font->lfWeight > 550) ? "bold" : "medium";
162     slant = font->lfItalic ? 'i' : 'r';
163     if (font->lfHeight == -1)
164         height = 0;
165     else
166         height = font->lfHeight * dc->vportExtX / dc->wndExtX;
167     if (height == 0) height = 120;  /* Default height = 12 */
168     else if (height < 0)
169     {
170         /* If height is negative, it means the height of the characters */
171         /* *without* the internal leading. So we adjust it a bit to     */
172         /* compensate. 5/4 seems to give good results for small fonts.  */
173         /* 
174          * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write 
175         height = 10 * (-height * 9 / 8);
176          * may be we have to use an non linear function
177         */
178         /* assume internal leading is 2 pixels. Else small fonts will become
179          * very small. */
180         height = (height-2) * -10; 
181     }
182     else height *= 10;
183     width  = 10 * (font->lfWidth * dc->vportExtY / dc->wndExtY);
184     if (width < 0) {
185         dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
186                       width, font->lfWidth );
187         width = -width;
188     }
189
190     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
191               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
192     
193   
194     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
195     if (*font->lfFaceName) {
196         family = FONT_ChkX11Family(font->lfFaceName);
197         /*--do _not_ translate if lfFaceName is family from X11  A.K.*/
198         if (!family) 
199           family = FONT_TranslateName( font->lfFaceName );
200         /* FIX ME: I don't if that's correct but it works J.M. */
201         spacing = '*';
202         }
203     else switch(font->lfPitchAndFamily & 0xf0)
204     {
205     case FF_ROMAN:
206       family = FONT_TranslateName( "roman" );
207       break;
208     case FF_SWISS:
209       family = FONT_TranslateName( "swiss" );
210       break;
211     case FF_MODERN:
212       family = FONT_TranslateName( "modern" );
213       break;
214     case FF_SCRIPT:
215       family = FONT_TranslateName( "script" );
216       break;
217     case FF_DECORATIVE:
218       family = FONT_TranslateName( "decorative" );
219       break;
220     default:
221       family = "*-*";
222       break;
223     }
224     sprintf( pattern, "-%s-%s-*-normal-*-*-*-*-*-*-*-%s",
225             family, weight, charset);
226     dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
227     names = XListFonts( display, pattern, 1, &count );
228     if (names) XFreeFontNames( names );
229     else
230     {
231         if (strcmp(family, "*-*") == 0)
232         {
233             fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
234             return NULL;
235         }
236         else family = "*-*";
237     }
238     oldheight = height;
239     oldspacing = spacing;
240     while (TRUE) {
241             /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
242             if ( width == 0 )
243               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
244                       family, weight, slant, height, spacing, charset);
245             else
246               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
247                       family, weight, slant, height, spacing, width, charset);
248             dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
249             names = XListFonts( display, pattern, 1, &count );
250             if (count > 0) break;
251             if (spacing == 'm') /* try 'c' if no 'm' found */ {
252
253                 spacing = 'c';
254                 continue;
255             } else if (spacing == 'p') /* try '*' if no 'p' found */ {
256                 spacing = '*';
257                 continue;
258             }
259             spacing = oldspacing;
260             height -= 10;               
261             if (height < 10) {
262                 if (slant == 'i') {
263                     /* try oblique if no italic font */
264                     slant = 'o';
265                     height = oldheight;
266                     continue;
267                 }
268                 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
269                     /* If a fixed spacing font could not be found, ignore
270                      * the family */
271                     family = "*-*";
272                     height = oldheight;
273                     continue;
274                 }
275                 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
276                 return NULL;
277             }
278     }
279     dprintf_font(stddeb,"        Found '%s'\n", *names );
280     if (!*font->lfFaceName)
281       ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
282     /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
283     /*AnsiUpper(font->lfFaceName);*/
284
285     fontStruct = XLoadQueryFont( display, *names );
286     XFreeFontNames( names );
287     return fontStruct;
288 }
289
290
291 /***********************************************************************
292  *           FONT_LOGFONT32AToLOGFONT16
293  */
294 static void FONT_LOGFONT32AToLOGFONT16( const LOGFONT32A *font,
295                                         LPLOGFONT16 font16 )
296 {
297     font16->lfHeight         = (INT16)font->lfHeight;
298     font16->lfWidth          = (INT16)font->lfWidth;
299     font16->lfEscapement     = (INT16)font->lfEscapement;
300     font16->lfOrientation    = (INT16)font->lfOrientation;
301     font16->lfWeight         = (INT16)font->lfWeight;
302     font16->lfItalic         = font->lfItalic;
303     font16->lfUnderline      = font->lfUnderline;
304     font16->lfStrikeOut      = font->lfStrikeOut;
305     font16->lfCharSet        = font->lfCharSet;
306     font16->lfOutPrecision   = font->lfOutPrecision;
307     font16->lfClipPrecision  = font->lfClipPrecision;
308     font16->lfQuality        = font->lfQuality;
309     font16->lfPitchAndFamily = font->lfPitchAndFamily;
310     lstrcpyn32A( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
311 }
312
313
314 /***********************************************************************
315  *           FONT_LOGFONT32WToLOGFONT16
316  */
317 static void FONT_LOGFONT32WToLOGFONT16( const LOGFONT32W *font,
318                                         LPLOGFONT16 font16 )
319 {
320     font16->lfHeight         = (INT16)font->lfHeight;
321     font16->lfWidth          = (INT16)font->lfWidth;
322     font16->lfEscapement     = (INT16)font->lfEscapement;
323     font16->lfOrientation    = (INT16)font->lfOrientation;
324     font16->lfWeight         = (INT16)font->lfWeight;
325     font16->lfItalic         = font->lfItalic;
326     font16->lfUnderline      = font->lfUnderline;
327     font16->lfStrikeOut      = font->lfStrikeOut;
328     font16->lfCharSet        = font->lfCharSet;
329     font16->lfOutPrecision   = font->lfOutPrecision;
330     font16->lfClipPrecision  = font->lfClipPrecision;
331     font16->lfQuality        = font->lfQuality;
332     font16->lfPitchAndFamily = font->lfPitchAndFamily;
333     lstrcpynWtoA( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
334 }
335
336
337 /***********************************************************************
338  *           FONT_LOGFONT16ToLOGFONT32A
339  */
340 static void FONT_LOGFONT16ToLOGFONT32A( LPLOGFONT16 font,
341                                         LPLOGFONT32A font32A )
342 {
343     font32A->lfHeight         = (INT32)font->lfHeight;
344     font32A->lfWidth          = (INT32)font->lfWidth;
345     font32A->lfEscapement     = (INT32)font->lfEscapement;
346     font32A->lfOrientation    = (INT32)font->lfOrientation;
347     font32A->lfWeight         = (INT32)font->lfWeight;
348     font32A->lfItalic         = font->lfItalic;
349     font32A->lfUnderline      = font->lfUnderline;
350     font32A->lfStrikeOut      = font->lfStrikeOut;
351     font32A->lfCharSet        = font->lfCharSet;
352     font32A->lfOutPrecision   = font->lfOutPrecision;
353     font32A->lfClipPrecision  = font->lfClipPrecision;
354     font32A->lfQuality        = font->lfQuality;
355     font32A->lfPitchAndFamily = font->lfPitchAndFamily;
356     lstrcpyn32A( font32A->lfFaceName, font->lfFaceName, LF_FACESIZE );
357 }
358
359
360 /***********************************************************************
361  *           FONT_LOGFONT16ToLOGFONT32W
362  */
363 static void FONT_LOGFONT16ToLOGFONT32W( LPLOGFONT16 font,
364                                         LPLOGFONT32W font32W )
365 {
366     font32W->lfHeight         = (INT32)font->lfHeight;
367     font32W->lfWidth          = (INT32)font->lfWidth;
368     font32W->lfEscapement     = (INT32)font->lfEscapement;
369     font32W->lfOrientation    = (INT32)font->lfOrientation;
370     font32W->lfWeight         = (INT32)font->lfWeight;
371     font32W->lfItalic         = font->lfItalic;
372     font32W->lfUnderline      = font->lfUnderline;
373     font32W->lfStrikeOut      = font->lfStrikeOut;
374     font32W->lfCharSet        = font->lfCharSet;
375     font32W->lfOutPrecision   = font->lfOutPrecision;
376     font32W->lfClipPrecision  = font->lfClipPrecision;
377     font32W->lfQuality        = font->lfQuality;
378     font32W->lfPitchAndFamily = font->lfPitchAndFamily;
379     lstrcpynAtoW( font32W->lfFaceName, font->lfFaceName, LF_FACESIZE );
380 }
381
382
383 /***********************************************************************
384  *           FONT_GetMetrics
385  */
386 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
387                       TEXTMETRIC16 * metrics )
388 {    
389     int average, i, count;
390     unsigned long prop;
391         
392     metrics->tmAscent  = xfont->ascent;
393     metrics->tmDescent = xfont->descent;
394     metrics->tmHeight  = xfont->ascent + xfont->descent;
395
396     metrics->tmInternalLeading  = 0;
397     if (XGetFontProperty( xfont, XA_CAP_HEIGHT, &prop ))
398         metrics->tmInternalLeading = xfont->ascent+xfont->descent-(INT16)prop;
399
400     metrics->tmExternalLeading  = 0;
401     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
402     metrics->tmWeight           = logfont->lfWeight;
403     metrics->tmItalic           = logfont->lfItalic;
404     metrics->tmUnderlined       = logfont->lfUnderline;
405     metrics->tmStruckOut        = logfont->lfStrikeOut;
406     metrics->tmFirstChar        = xfont->min_char_or_byte2;
407     metrics->tmLastChar         = xfont->max_char_or_byte2;
408     metrics->tmDefaultChar      = xfont->default_char;
409     metrics->tmBreakChar        = ' ';
410     metrics->tmCharSet          = logfont->lfCharSet;
411     metrics->tmOverhang         = 0;
412     metrics->tmDigitizedAspectX = 1;
413     metrics->tmDigitizedAspectY = 1;
414     metrics->tmPitchAndFamily   = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
415
416     /* TMPF_FIXED_PITCH bit means variable pitch...Don't you love Microsoft? */
417     if (xfont->min_bounds.width != xfont->max_bounds.width)
418         metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
419
420     if (!xfont->per_char) average = metrics->tmMaxCharWidth;
421     else
422     {
423         XCharStruct * charPtr = xfont->per_char;
424         average = count = 0;
425         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
426         {
427             if (!CI_NONEXISTCHAR( charPtr ))
428             {
429                 average += charPtr->width;
430                 count++;
431             }
432             charPtr++;
433         }
434         if (count) average = (average + count/2) / count;
435     }
436     metrics->tmAveCharWidth = average;
437 }
438
439 /***********************************************************************
440  *           GetGlyphOutLine    (GDI.309)
441  */
442 DWORD GetGlyphOutLine( HDC16 hdc, UINT uChar, UINT fuFormat,
443                        LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPSTR lpBuffer,
444                        LPMAT2 lpmat2) 
445 {
446     fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
447              hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
448     return (DWORD)-1; /* failure */
449 }
450
451
452 /***********************************************************************
453  *           CreateScalableFontResource    (GDI.310)
454  */
455 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
456                                  LPSTR lpszFontFile, LPSTR lpszCurrentPath )
457 {
458     /* fHidden=1 - only visible for the calling app, read-only, not
459      * enumbered with EnumFonts/EnumFontFamilies
460      * lpszCurrentPath can be NULL
461      */
462     fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
463             fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
464     return FALSE; /* create failed */
465 }
466
467
468 /***********************************************************************
469  *           CreateFontIndirect16   (GDI.57)
470  */
471 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
472 {
473     FONTOBJ * fontPtr;
474     HFONT16 hfont;
475
476     if (!font)
477     {
478         fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
479         return 0;
480     }
481     hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
482     if (!hfont) return 0;
483     fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
484     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
485     dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
486         font, font->lfHeight, font->lfWidth, hfont);
487     return hfont;
488 }
489
490
491 /***********************************************************************
492  *           CreateFontIndirect32A   (GDI32.44)
493  */
494 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
495 {
496     LOGFONT16 font16;
497
498     FONT_LOGFONT32AToLOGFONT16(font,&font16);
499
500     return CreateFontIndirect16( &font16 );
501 }
502
503
504 /***********************************************************************
505  *           CreateFontIndirect32W   (GDI32.45)
506  */
507 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
508 {
509     LOGFONT16 font16;
510
511     FONT_LOGFONT32WToLOGFONT16(font,&font16);
512     return CreateFontIndirect16( &font16 );
513 }
514
515
516 /***********************************************************************
517  *           CreateFont16    (GDI.56)
518  */
519 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
520                       INT16 weight, BYTE italic, BYTE underline,
521                       BYTE strikeout, BYTE charset, BYTE outpres,
522                       BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
523 {
524     LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
525                       strikeout, charset, outpres, clippres, quality, pitch, };
526     dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
527     if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
528     else logfont.lfFaceName[0] = '\0';
529     return CreateFontIndirect16( &logfont );
530 }
531
532
533
534 /*************************************************************************
535  *           CreateFont32A    (GDI32.43)
536  */
537 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
538                        INT32 weight, DWORD italic, DWORD underline,
539                        DWORD strikeout, DWORD charset, DWORD outpres,
540                        DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
541 {
542     return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
543                                   underline, strikeout, charset, outpres,
544                                   clippres, quality, pitch, name );
545 }
546
547
548 /*************************************************************************
549  *           CreateFont32W    (GDI32.46)
550  */
551 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
552                        INT32 weight, DWORD italic, DWORD underline,
553                        DWORD strikeout, DWORD charset, DWORD outpres,
554                        DWORD clippres, DWORD quality, DWORD pitch,
555                        LPCWSTR name )
556 {
557     LPSTR namea = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
558     HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
559                                          italic, underline, strikeout, charset,
560                                          outpres, clippres, quality, pitch,
561                                          namea );
562     HeapFree( GetProcessHeap(), 0, namea );
563     return ret;
564 }
565
566
567 /***********************************************************************
568  *           FONT_GetObject16
569  */
570 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
571 {
572     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
573     memcpy( buffer, &font->logfont, count );
574     return count;
575 }
576
577
578 /***********************************************************************
579  *           FONT_GetObject32A
580  */
581 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
582 {
583     LOGFONT32A fnt32;
584
585     memset(&fnt32, 0, sizeof(fnt32));
586     fnt32.lfHeight         = font->logfont.lfHeight;
587     fnt32.lfWidth          = font->logfont.lfWidth;
588     fnt32.lfEscapement     = font->logfont.lfEscapement;
589     fnt32.lfOrientation    = font->logfont.lfOrientation;
590     fnt32.lfWeight         = font->logfont.lfWeight;
591     fnt32.lfItalic         = font->logfont.lfItalic;
592     fnt32.lfUnderline      = font->logfont.lfUnderline;
593     fnt32.lfStrikeOut      = font->logfont.lfStrikeOut;
594     fnt32.lfCharSet        = font->logfont.lfCharSet;
595     fnt32.lfOutPrecision   = font->logfont.lfOutPrecision;
596     fnt32.lfClipPrecision  = font->logfont.lfClipPrecision;
597     fnt32.lfQuality        = font->logfont.lfQuality;
598     fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
599     strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
600              sizeof(fnt32.lfFaceName) );
601
602     if (count > sizeof(fnt32)) count = sizeof(fnt32);
603     memcpy( buffer, &fnt32, count );
604     return count;
605 }
606
607
608 /***********************************************************************
609  *           FONT_SelectObject
610  */
611 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
612 {
613     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
614
615     static struct {
616                 HFONT16         id;
617                 LOGFONT16       logfont;
618                 int             access;
619                 int             used;
620                 X_PHYSFONT      cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
621     int         i;
622
623     X_PHYSFONT * stockPtr;
624     HFONT16 prevHandle = dc->w.hFont;
625     XFontStruct * fontStruct;
626     dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
627
628 #if 0 /* From the code in SelectObject, this can not happen */
629       /* Load font if necessary */
630     if (!font)
631     {
632         HFONT16 hnewfont;
633
634         hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
635                               FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
636                               DEFAULT_QUALITY, FF_DONTCARE, "*" );
637         font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
638     }
639 #endif
640
641     if (dc->header.wMagic == METAFILE_DC_MAGIC)
642       if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
643         return prevHandle;
644       else
645         return 0;
646
647     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
648         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
649     else {
650         stockPtr = NULL;
651         /*
652          * Ok, It's not a stock font but 
653          * may be it's cached in dynamic cache
654          */
655         for(i=0; i<FONTCACHE; i++) /* search for same handle */
656              if (cacheFonts[i].id==hfont) { /* Got the handle */
657                 /*
658                  * Check if Handle matches the font 
659                  */
660                 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
661                         /* No: remove handle id from dynamic font cache */
662                         cacheFonts[i].access=0;
663                         cacheFonts[i].used=0;
664                         cacheFonts[i].id=0;
665                         /* may be there is an unused handle which contains the font */
666                         for(i=0; i<FONTCACHE; i++) {
667                                 if((cacheFonts[i].used == 0) &&
668                                   (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
669                                         /* got it load from cache and set new handle id */
670                                         stockPtr = &cacheFonts[i].cacheFont;
671                                         cacheFonts[i].access=1;
672                                         cacheFonts[i].used=1;
673                                         cacheFonts[i].id=hfont;
674                                         dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
675                                         break;
676                                         }
677                                 }
678         
679                         }
680                 else {
681                         /* Yes: load from dynamic font cache */
682                         stockPtr = &cacheFonts[i].cacheFont;
683                         cacheFonts[i].access++;
684                         cacheFonts[i].used++;
685                         }
686                 break;
687                 }
688         }
689     if (!stockPtr || !stockPtr->fstruct)
690     {
691         if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
692         {
693               /* If it is not a stock font, we can simply return 0 */
694             if (!stockPtr) return 0;
695               /* Otherwise we must try to find a substitute */
696             dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
697             font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
698             font->logfont.lfPitchAndFamily |= FIXED_PITCH;
699             fontStruct = XLoadQueryFont( display, "fixed" );
700             if (!fontStruct)
701             {
702                 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
703                 exit( 1 );
704             }
705         }
706     }
707     else
708     {
709         fontStruct = stockPtr->fstruct;
710         dprintf_font(stddeb,
711                      "FONT_SelectObject: Loaded font from cache %04x %p\n",
712                      hfont, fontStruct );
713     }   
714
715       /* Unuse previous font */
716         for (i=0; i < FONTCACHE; i++) {
717                 if (cacheFonts[i].id == prevHandle) {
718                         if(cacheFonts[i].used == 0)
719                                 fprintf(stderr, "Trying to decrement a use count of 0.\n");
720                         else 
721                                 cacheFonts[i].used--;
722                 }
723         }
724
725       /* Store font */
726     dc->w.hFont = hfont;
727     if (stockPtr)
728     {
729         if (!stockPtr->fstruct)
730         {
731             stockPtr->fstruct = fontStruct;
732             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
733         }
734         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
735     }
736     else
737     {
738         /* 
739          * Check in cacheFont
740          */
741         cacheFontsMin=NULL;
742         for (i=0; i < FONTCACHE; i++) {
743                 if (cacheFonts[i].used==0) 
744                         if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
745                                 cacheFontsMin=&cacheFonts[i];
746                 }
747         if (!cacheFontsMin) {
748                 fprintf(stderr,"No unused font cache entry !!!!\n" );
749                 return prevHandle;
750         }
751         if (cacheFontsMin->id!=0) {
752                 dprintf_font(stddeb,
753                         "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
754                 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
755                 }
756         cacheFontsMin->cacheFont.fstruct = fontStruct;
757         FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
758         cacheFontsMin->access=1;
759         cacheFontsMin->used=1;
760         cacheFontsMin->id=hfont;
761         memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
762         memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
763
764     }
765     return prevHandle;
766 }
767
768
769 /***********************************************************************
770  *           GetTextCharacterExtra16    (GDI.89)
771  */
772 INT16 GetTextCharacterExtra16( HDC16 hdc )
773 {
774     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
775     if (!dc) return 0;
776     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
777                  / dc->vportExtX );
778 }
779
780
781 /***********************************************************************
782  *           GetTextCharacterExtra32    (GDI32.225)
783  */
784 INT32 GetTextCharacterExtra32( HDC32 hdc )
785 {
786     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
787     if (!dc) return 0;
788     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
789                  / dc->vportExtX );
790 }
791
792
793 /***********************************************************************
794  *           SetTextCharacterExtra16    (GDI.8)
795  */
796 INT16 SetTextCharacterExtra16( HDC16 hdc, INT16 extra )
797 {
798     return (INT16)SetTextCharacterExtra32( hdc, extra );
799 }
800
801
802 /***********************************************************************
803  *           SetTextCharacterExtra32    (GDI32.337)
804  */
805 INT32 SetTextCharacterExtra32( HDC32 hdc, INT32 extra )
806 {
807     INT32 prev;
808     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
809     if (!dc) return 0;
810     extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;    
811     prev = dc->w.charExtra;
812     dc->w.charExtra = abs(extra);
813     return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
814 }
815
816
817 /***********************************************************************
818  *           SetTextJustification16    (GDI.10)
819  */
820 INT16 SetTextJustification16( HDC16 hdc, INT16 extra, INT16 breaks )
821 {
822     return SetTextJustification32( hdc, extra, breaks );
823 }
824
825
826 /***********************************************************************
827  *           SetTextJustification32    (GDI32.339)
828  */
829 BOOL32 SetTextJustification32( HDC32 hdc, INT32 extra, INT32 breaks )
830 {
831     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
832     if (!dc) return 0;
833
834     extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
835     if (!extra) breaks = 0;
836     dc->w.breakTotalExtra = extra;
837     dc->w.breakCount = breaks;
838     if (breaks)
839     {   
840         dc->w.breakExtra = extra / breaks;
841         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
842     }
843     else
844     {
845         dc->w.breakExtra = 0;
846         dc->w.breakRem   = 0;
847     }
848     return 1;
849 }
850
851
852 /***********************************************************************
853  *           GetTextFace16    (GDI.92)
854  */
855 INT16 GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
856 {
857         return GetTextFace32A(hdc,count,name);
858 }
859
860 /***********************************************************************
861  *           GetTextFace32A    (GDI32.234)
862  */
863 INT32 GetTextFace32A( HDC32 hdc, INT32 count, LPSTR name )
864 {
865     FONTOBJ *font;
866
867     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
868     if (!dc) return 0;
869     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
870         return 0;
871     lstrcpyn32A( name, font->logfont.lfFaceName, count );
872     return strlen(name);
873 }
874
875 /***********************************************************************
876  *           GetTextFace32W    (GDI32.235)
877  */
878 INT32 GetTextFace32W( HDC32 hdc, INT32 count, LPWSTR name )
879 {
880     LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
881     INT32 res = GetTextFace32A(hdc,count,nameA);
882     lstrcpyAtoW( name, nameA );
883     HeapFree( GetProcessHeap(), 0, nameA );
884     return res;
885 }
886
887
888 /***********************************************************************
889  *           GetTextExtent    (GDI.91)
890  */
891 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, INT16 count )
892 {
893     SIZE16 size;
894     if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
895     return MAKELONG( size.cx, size.cy );
896 }
897
898
899 /***********************************************************************
900  *           GetTextExtentPoint16    (GDI.471)
901  *
902  * FIXME: Should this have a bug for compatibility?
903  * Original Windows versions of GetTextExtentPoint{A,W} have documented
904  * bugs.
905  */
906 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
907 {
908     SIZE32 size32;
909     BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
910     CONV_SIZE32TO16( &size32, size );
911     return (BOOL16)ret;
912 }
913
914
915 /***********************************************************************
916  *           GetTextExtentPoint32A    (GDI32.230)
917  */
918 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
919                               LPSIZE32 size )
920 {
921     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
922     if (!dc)
923     {
924         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
925             return FALSE;
926     }
927
928     if (!dc->funcs->pGetTextExtentPoint ||
929         !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
930         return FALSE;
931
932     dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
933                  hdc, count, str, count, size, size->cx, size->cy );
934     return TRUE;
935 }
936
937
938 /***********************************************************************
939  *           GetTextExtentPoint32W    (GDI32.231)
940  */
941 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
942                               LPSIZE32 size )
943 {
944     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
945     BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
946     HeapFree( GetProcessHeap(), 0, p );
947     return ret;
948 }
949
950 /***********************************************************************
951  *           GetTextExtentPoint32ABuggy    (GDI32.232)
952  */
953 BOOL32 GetTextExtentPoint32ABuggy( HDC32 hdc, LPCSTR str, INT32 count,
954                                    LPSIZE32 size )
955 {
956     dprintf_font( stddeb, "GetTextExtentPoint32ABuggy: not bug compatible.\n");
957     return GetTextExtentPoint32A( hdc, str, count, size );
958 }
959
960 /***********************************************************************
961  *           GetTextExtentPoint32WBuggy    (GDI32.233)
962  */
963 BOOL32 GetTextExtentPoint32WBuggy( HDC32 hdc, LPCWSTR str, INT32 count,
964                                    LPSIZE32 size )
965 {
966     dprintf_font( stddeb, "GetTextExtentPoint32WBuggy: not bug compatible.\n");
967     return GetTextExtentPoint32W( hdc, str, count, size );
968 }
969
970
971 /***********************************************************************
972  *           GetTextExtentExPoint32A    (GDI32.228)
973  */
974 BOOL32 GetTextExtentExPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
975                                 INT32 maxExt,LPINT32 lpnFit, LPINT32 alpDx,
976                                 LPSIZE32 size )
977 {
978   int index;
979   SIZE32 tSize;
980   int nFit=0;
981   int extent=0;
982   DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
983   if (!dc)
984     {
985       if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
986         return FALSE;
987     }
988   if (!dc->funcs->pGetTextExtentPoint) return FALSE;
989
990   size->cx=0; size->cy=0;
991   for(index=0;index<count;index++)
992     {
993       if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
994       if(extent+tSize.cx<maxExt)
995         {
996           extent+=tSize.cx;
997           nFit++;
998           str++;
999           if(alpDx) alpDx[index]=extent;
1000           if(tSize.cy > size->cy) size->cy=tSize.cy;
1001         }
1002       else break;
1003     }
1004   size->cx=extent;
1005   *lpnFit=nFit;
1006   dprintf_font(stddeb,"GetTextExtentExPoint32A(%08x '%.*s' %d) returning %d %d %d\n",
1007                hdc,count,str,maxExt,nFit, size->cx,size->cy);
1008   return TRUE;
1009 }
1010
1011 /***********************************************************************
1012  *           GetTextExtentExPoint32W    (GDI32.229)
1013  */
1014
1015 BOOL32 GetTextExtentExPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
1016                                 INT32 maxExt, LPINT32 lpnFit, LPINT32 alpDx,
1017                                 LPSIZE32 size )
1018 {
1019     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
1020     BOOL32 ret = GetTextExtentExPoint32A( hdc, p, count, maxExt,
1021                                         lpnFit, alpDx, size);
1022     HeapFree( GetProcessHeap(), 0, p );
1023     return ret;
1024 }
1025
1026 /***********************************************************************
1027  *           GetTextMetrics16    (GDI.93)
1028  */
1029 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
1030 {
1031     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1032     if (!dc) return FALSE;
1033     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
1034
1035     metrics->tmAscent  = abs( metrics->tmAscent
1036                               * dc->wndExtY / dc->vportExtY );
1037     metrics->tmDescent = abs( metrics->tmDescent
1038                               * dc->wndExtY / dc->vportExtY );
1039     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
1040     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
1041                                       * dc->wndExtY / dc->vportExtY );
1042     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
1043                                       * dc->wndExtY / dc->vportExtY );
1044     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
1045                                       * dc->wndExtX / dc->vportExtX );
1046     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
1047                                       * dc->wndExtX / dc->vportExtX );
1048
1049     dprintf_font(stdnimp,"text metrics:\n
1050         InternalLeading = %i
1051         ExternalLeading = %i
1052         MaxCharWidth = %i
1053         Weight = %i
1054         Italic = %i
1055         Underlined = %i
1056         StruckOut = %i
1057         FirstChar = %i
1058         LastChar = %i
1059         DefaultChar = %i
1060         BreakChar = %i
1061         CharSet = %i
1062         Overhang = %i
1063         DigitizedAspectX = %i
1064         DigitizedAspectY = %i
1065         AveCharWidth = %i
1066         MaxCharWidth = %i
1067         Ascent = %i
1068         Descent = %i
1069         Height = %i\n",
1070     metrics->tmInternalLeading,
1071     metrics->tmExternalLeading,
1072     metrics->tmMaxCharWidth,
1073     metrics->tmWeight,
1074     metrics->tmItalic,
1075     metrics->tmUnderlined,
1076     metrics->tmStruckOut,
1077     metrics->tmFirstChar,
1078     metrics->tmLastChar,
1079     metrics->tmDefaultChar,
1080     metrics->tmBreakChar,
1081     metrics->tmCharSet,
1082     metrics->tmOverhang,
1083     metrics->tmDigitizedAspectX,
1084     metrics->tmDigitizedAspectY,
1085     metrics->tmAveCharWidth,
1086     metrics->tmMaxCharWidth,
1087     metrics->tmAscent,
1088     metrics->tmDescent,
1089     metrics->tmHeight);
1090
1091     return TRUE;
1092 }
1093
1094
1095 /***********************************************************************
1096  *           GetTextMetrics32A    (GDI32.236)
1097  */
1098 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
1099 {
1100     TEXTMETRIC16 tm;
1101     if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1102     metrics->tmHeight           = tm.tmHeight;
1103     metrics->tmAscent           = tm.tmAscent;
1104     metrics->tmDescent          = tm.tmDescent;
1105     metrics->tmInternalLeading  = tm.tmInternalLeading;
1106     metrics->tmExternalLeading  = tm.tmExternalLeading;
1107     metrics->tmAveCharWidth     = tm.tmAveCharWidth;
1108     metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
1109     metrics->tmWeight           = tm.tmWeight;
1110     metrics->tmOverhang         = tm.tmOverhang;
1111     metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1112     metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1113     metrics->tmFirstChar        = tm.tmFirstChar;
1114     metrics->tmLastChar         = tm.tmLastChar;
1115     metrics->tmDefaultChar      = tm.tmDefaultChar;
1116     metrics->tmBreakChar        = tm.tmBreakChar;
1117     metrics->tmItalic           = tm.tmItalic;
1118     metrics->tmUnderlined       = tm.tmUnderlined;
1119     metrics->tmStruckOut        = tm.tmStruckOut;
1120     metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
1121     metrics->tmCharSet          = tm.tmCharSet;
1122     return TRUE;
1123 }
1124
1125
1126 /***********************************************************************
1127  *           GetTextMetrics32W    (GDI32.237)
1128  */
1129 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
1130 {
1131     TEXTMETRIC16 tm;
1132     if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1133     metrics->tmHeight           = tm.tmHeight;
1134     metrics->tmAscent           = tm.tmAscent;
1135     metrics->tmDescent          = tm.tmDescent;
1136     metrics->tmInternalLeading  = tm.tmInternalLeading;
1137     metrics->tmExternalLeading  = tm.tmExternalLeading;
1138     metrics->tmAveCharWidth     = tm.tmAveCharWidth;
1139     metrics->tmMaxCharWidth     = tm.tmMaxCharWidth;
1140     metrics->tmWeight           = tm.tmWeight;
1141     metrics->tmOverhang         = tm.tmOverhang;
1142     metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1143     metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1144     metrics->tmFirstChar        = tm.tmFirstChar;
1145     metrics->tmLastChar         = tm.tmLastChar;
1146     metrics->tmDefaultChar      = tm.tmDefaultChar;
1147     metrics->tmBreakChar        = tm.tmBreakChar;
1148     metrics->tmItalic           = tm.tmItalic;
1149     metrics->tmUnderlined       = tm.tmUnderlined;
1150     metrics->tmStruckOut        = tm.tmStruckOut;
1151     metrics->tmPitchAndFamily   = tm.tmPitchAndFamily;
1152     metrics->tmCharSet          = tm.tmCharSet;
1153     return TRUE;
1154 }
1155
1156
1157 /***********************************************************************
1158  *           SetMapperFlags    (GDI.349)
1159  */
1160 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
1161 {
1162     dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n", 
1163                  hDC, dwFlag); 
1164     return 0L;
1165 }
1166
1167  
1168 /***********************************************************************
1169  *           GetCharABCWidths16   (GDI.307)
1170  */
1171 BOOL16 GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1172                            LPABC16 abc )
1173 {
1174     ABC32 abc32;
1175     if (!GetCharABCWidths32A( hdc, firstChar, lastChar, &abc32 )) return FALSE;
1176     abc->abcA = abc32.abcA;
1177     abc->abcB = abc32.abcB;
1178     abc->abcC = abc32.abcC;
1179     return TRUE;
1180 }
1181
1182
1183 /***********************************************************************
1184  *           GetCharABCWidths32A   (GDI32.149)
1185  */
1186 BOOL32 GetCharABCWidths32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1187                             LPABC32 abc )
1188 {
1189     /* No TrueType fonts in Wine so far */
1190     fprintf( stdnimp, "STUB: GetCharABCWidths(%04x,%04x,%04x,%p)\n",
1191              hdc, firstChar, lastChar, abc );
1192     return FALSE;
1193 }
1194
1195
1196 /***********************************************************************
1197  *           GetCharABCWidths32W   (GDI32.152)
1198  */
1199 BOOL32 GetCharABCWidths32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1200                             LPABC32 abc )
1201 {
1202     return GetCharABCWidths32A( hdc, firstChar, lastChar, abc );
1203 }
1204
1205
1206 /***********************************************************************
1207  *           GetCharWidth16    (GDI.350)
1208  */
1209 BOOL16 GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1210                        LPINT16 buffer )
1211 {
1212     int i, width;
1213     XFontStruct *xfont;
1214     XCharStruct *cs, *def;
1215
1216     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1217     if (!dc) return FALSE;
1218     xfont = dc->u.x.font.fstruct;
1219     
1220     /* fixed font? */
1221     if (xfont->per_char == NULL)
1222     {
1223         for (i = firstChar; i <= lastChar; i++)
1224             *buffer++ = xfont->max_bounds.width;
1225         return TRUE;
1226     }
1227
1228     CI_GET_DEFAULT_INFO(xfont, def);
1229         
1230     for (i = firstChar; i <= lastChar; i++)
1231     {
1232         CI_GET_CHAR_INFO( xfont, i, def, cs );
1233         width = cs ? cs->width : xfont->max_bounds.width;
1234         *buffer++ = MAX( width, 0 );
1235     }
1236     return TRUE;
1237 }
1238
1239
1240 /***********************************************************************
1241  *           GetCharWidth32A    (GDI32.155)
1242  */
1243 BOOL32 GetCharWidth32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1244                         LPINT32 buffer )
1245 {
1246     int i, width;
1247     XFontStruct *xfont;
1248     XCharStruct *cs, *def;
1249
1250     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1251     if (!dc) return FALSE;
1252     xfont = dc->u.x.font.fstruct;
1253     
1254     /* fixed font? */
1255     if (xfont->per_char == NULL)
1256     {
1257         for (i = firstChar; i <= lastChar; i++)
1258             *buffer++ = xfont->max_bounds.width;
1259         return TRUE;
1260     }
1261
1262     CI_GET_DEFAULT_INFO(xfont, def);
1263         
1264     for (i = firstChar; i <= lastChar; i++)
1265     {
1266         CI_GET_CHAR_INFO( xfont, i, def, cs );
1267         width = cs ? cs->width : xfont->max_bounds.width;
1268         *buffer++ = MAX( width, 0 );
1269     }
1270     return TRUE;
1271 }
1272
1273
1274 /***********************************************************************
1275  *           GetCharWidth32W    (GDI32.158)
1276  */
1277 BOOL32 GetCharWidth32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1278                         LPINT32 buffer )
1279 {
1280     return GetCharWidth32A( hdc, firstChar, lastChar, buffer );
1281 }
1282
1283
1284 /***********************************************************************
1285  *           AddFontResource    (GDI.119)
1286  */
1287 INT AddFontResource( LPCSTR str )
1288 {
1289     fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1290     return 1;
1291 }
1292
1293
1294 /***********************************************************************
1295  *           RemoveFontResource    (GDI.136)
1296  */
1297 BOOL RemoveFontResource( LPSTR str )
1298 {
1299     fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1300     return TRUE;
1301 }
1302
1303
1304 /*************************************************************************
1305  *                              ParseFontParms          [internal]
1306  */
1307 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1308 {
1309         int     i;
1310         if (lpFont == NULL) return 0;
1311         if (lpRetStr == NULL) return 0;
1312         for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1313                 if (*lpFont == '-') i++;
1314                 lpFont++;
1315                 }
1316         if (i == wParmsNo) {
1317                 if (*lpFont == '-') lpFont++;
1318                 wMaxSiz--;
1319                 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1320                         *(lpRetStr + i) = *lpFont++;
1321                 *(lpRetStr + i) = '\0';
1322                 return i;
1323                 }
1324         else
1325                 lpRetStr[0] = '\0';
1326         return 0;
1327 }
1328
1329
1330 /*************************************************************************
1331  *                              InitFontsList           [internal]
1332  */
1333
1334 static int logfcmp(const void *a,const void *b) 
1335 {
1336   return lstrcmpi32A( (*(LPLOGFONT16 *)a)->lfFaceName,
1337                       (*(LPLOGFONT16 *)b)->lfFaceName );
1338 }
1339
1340 void InitFontsList(void)
1341 {
1342   char  str[32];
1343   char  pattern[100];
1344   char  *family, *weight, *charset;
1345   char  **names;
1346   char  slant, spacing;
1347   int   i, count;
1348   LPLOGFONT16 lpNewFont;
1349
1350   dprintf_font(stddeb,"InitFontsList !\n");
1351
1352   weight = "medium";
1353   slant = 'r';
1354   spacing = '*';
1355   charset = "*";
1356   family = "*-*";
1357
1358   sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1359           family, weight, slant, spacing, charset);
1360   names = XListFonts( display, pattern, MAX_FONTS, &count );
1361   dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1362
1363   lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1364   if (lpNewFont == NULL) {
1365       dprintf_font(stddeb,
1366                    "InitFontsList // Error alloc new font structure !\n");
1367       XFreeFontNames(names);
1368       return;
1369   }
1370
1371   for (i = 0; i < count; i++) {
1372     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1373
1374     ParseFontParms(names[i], 2, str, sizeof(str));
1375 /*    AnsiUpper(str);*/
1376     strcpy(lpNewFont->lfFaceName, str);
1377     ParseFontParms(names[i], 8, str, sizeof(str));
1378     lpNewFont->lfHeight = atoi(str) / 10;
1379     ParseFontParms(names[i], 12, str, sizeof(str));
1380     lpNewFont->lfWidth = atoi(str) / 10;
1381     lpNewFont->lfEscapement = 0;
1382     lpNewFont->lfOrientation = 0;
1383     lpNewFont->lfWeight = FW_REGULAR;
1384     lpNewFont->lfItalic = 0;
1385     lpNewFont->lfUnderline = 0;
1386     lpNewFont->lfStrikeOut = 0;
1387     ParseFontParms(names[i], 13, str, sizeof(str));
1388     if (strcmp(str, "iso8859") == 0)  {
1389       lpNewFont->lfCharSet = ANSI_CHARSET;
1390     } else  {
1391       lpNewFont->lfCharSet = OEM_CHARSET;
1392     }
1393     lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1394     lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1395     lpNewFont->lfQuality = DEFAULT_QUALITY;
1396     ParseFontParms(names[i], 11, str, sizeof(str));
1397     switch(str[0]) {
1398      case 'p':
1399       lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1400       break;
1401      case 'm':
1402      case 'c':
1403       lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1404       break;
1405      default:
1406       lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1407       break;
1408     }
1409     dprintf_font( stddeb,
1410                   "InitFontsList // lpNewFont->lfHeight=%d\n",
1411                   lpNewFont->lfHeight );
1412     dprintf_font( stddeb,
1413                   "InitFontsList // lpNewFont->lfWidth=%d\n",
1414                   lpNewFont->lfWidth );
1415     dprintf_font( stddeb,
1416                   "InitFontsList // lfFaceName='%s'\n",
1417                   lpNewFont->lfFaceName );
1418     lpLogFontList[i] = lpNewFont;
1419     lpNewFont = (LPLOGFONT16)
1420       ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1421   }
1422   lpLogFontList[i] = NULL;
1423
1424   qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1425   XFreeFontNames(names);
1426 }
1427
1428 /*************************************************************************
1429  *                              EnumFonts                       [GDI.70]
1430  * We reuse EnumFontFamilies* for the callback function get the same
1431  * structs (+ extra stuff at the end which will be ignored by the enum funcs)
1432  */
1433 INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1434 {
1435   return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
1436 }
1437
1438 /*************************************************************************
1439  *                              EnumFontsA                      [GDI32.84]
1440  */
1441 INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1442 {
1443   return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
1444 }
1445
1446 /*************************************************************************
1447  *                              EnumFontsA                      [GDI32.84]
1448  */
1449 INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1450 {
1451   return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
1452 }
1453
1454 /*************************************************************************
1455  *                              EnumFontFamilies        [GDI.330]
1456  */
1457 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1458 {
1459   LOGFONT16     LF;
1460
1461   if (lpszFamily)
1462      strcpy(LF.lfFaceName,lpszFamily);
1463   else
1464      LF.lfFaceName[0]='\0';
1465   LF.lfCharSet = DEFAULT_CHARSET;
1466
1467   return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
1468 }
1469
1470 /*************************************************************************
1471  *                              EnumFontFamiliesA       [GDI32.80]
1472  */
1473 INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1474 {
1475   LOGFONT32A    LF;
1476
1477   if (lpszFamily)
1478      strcpy(LF.lfFaceName,lpszFamily);
1479   else
1480      LF.lfFaceName[0]='\0';
1481   LF.lfCharSet = DEFAULT_CHARSET;
1482
1483   return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
1484 }
1485
1486 /*************************************************************************
1487  *                              EnumFontFamiliesW       [GDI32.83]
1488  */
1489 INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1490 {
1491   LOGFONT32W    LF;
1492
1493   if (lpszFamilyW)
1494         lstrcpy32W(LF.lfFaceName,lpszFamilyW);
1495   else
1496         LF.lfFaceName[0]=0;
1497   LF.lfCharSet = DEFAULT_CHARSET;
1498   return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
1499 }
1500
1501 /*************************************************************************
1502  *                              EnumFontFamiliesEx      [GDI.618]
1503  * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
1504  *        (applies to all EnumFontFamiliesEx*)
1505  *        winelib/16 support.
1506  */
1507 INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
1508 {
1509   HLOCAL16      hLog;
1510   HLOCAL16      hMet;
1511   HFONT16 hFont;
1512   HFONT16 hOldFont;
1513   LPENUMLOGFONTEX16 lpEnumLogFont;
1514   LPNEWTEXTMETRICEX16 lptm;
1515   LPSTR         lpOldName;
1516   char          FaceName[LF_FACESIZE];
1517   int           nRet = 0;
1518   int           i;
1519   
1520   dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
1521                hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
1522   if (lpEnumFunc == 0) return 0;
1523   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
1524   lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
1525   if (lpEnumLogFont == NULL) {
1526     fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
1527     return 0;
1528   }
1529   hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
1530   lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
1531   if (lptm == NULL) {
1532     GDI_HEAP_FREE(hLog);
1533     fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
1534     return 0;
1535   }
1536   lpOldName = NULL;
1537   strcpy(FaceName,lpLF->lfFaceName);
1538 /*  AnsiUpper(lpLF->lfFaceName);*/
1539
1540   if (lpLogFontList[0] == NULL) InitFontsList();
1541   for(i = 0; lpLogFontList[i] != NULL; i++) {
1542     /* lfCharSet */
1543     if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1544         if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1545            continue;
1546
1547     /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1548     /* lfFaceName */
1549     if (FaceName[0])
1550     {
1551         if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1552            continue;
1553     }
1554     else
1555     {
1556         if ((lpOldName!=NULL) &&
1557             !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1558            continue;
1559         lpOldName=lpLogFontList[i]->lfFaceName;
1560     }
1561
1562     memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1563     strcpy(lpEnumLogFont->elfFullName,"");
1564     strcpy(lpEnumLogFont->elfStyle,"");
1565     hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1566     hOldFont = SelectObject32(hDC, hFont);
1567     GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
1568     SelectObject32(hDC, hOldFont);
1569     DeleteObject32(hFont);
1570     dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1571     
1572     nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1573                        0, lpData );
1574     if (nRet == 0) {
1575       dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1576       break;
1577     }
1578   }
1579   GDI_HEAP_FREE(hMet);
1580   GDI_HEAP_FREE(hLog);
1581   return nRet;
1582 }
1583
1584 /*************************************************************************
1585  *                              EnumFontFamiliesExA     [GDI32.81]
1586  * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
1587  */
1588 INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
1589 {
1590   HLOCAL16      hLog;
1591   HLOCAL16      hMet;
1592   HFONT32       hFont;
1593   HFONT32       hOldFont;
1594   LPENUMLOGFONTEX32A    lpEnumLogFont;
1595   LPNEWTEXTMETRICEX32A  lptm;
1596   LPSTR         lpOldName;
1597   char          FaceName[LF_FACESIZE];
1598   int           nRet = 0;
1599   int           i;
1600   
1601   dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
1602                hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
1603   if (lpEnumFunc == 0) return 0;
1604   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
1605   lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
1606   if (lpEnumLogFont == NULL) {
1607     fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1608     return 0;
1609   }
1610   hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
1611   lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
1612   if (lptm == NULL) {
1613     GDI_HEAP_FREE(hLog);
1614     fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
1615     return 0;
1616   }
1617   lpOldName = NULL;
1618   strcpy(FaceName,lpLF->lfFaceName);
1619 /*  AnsiUpper(lpLF->lfFaceName);*/
1620
1621   if (lpLogFontList[0] == NULL) InitFontsList();
1622   for(i = 0; lpLogFontList[i] != NULL; i++) {
1623     /* lfCharSet */
1624     if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1625         if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1626            continue;
1627
1628     /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1629     /* lfFaceName */
1630     if (FaceName[0]) {
1631         if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1632            continue;
1633     } else {
1634         if ((lpOldName!=NULL) &&
1635             !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1636            continue;
1637         lpOldName=lpLogFontList[i]->lfFaceName;
1638     }
1639
1640     FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1641     strcpy(lpEnumLogFont->elfFullName,"");
1642     strcpy(lpEnumLogFont->elfStyle,"");
1643     strcpy(lpEnumLogFont->elfScript,"");
1644     hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
1645     hOldFont = SelectObject32(hDC, hFont);
1646     GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
1647     SelectObject32(hDC, hOldFont);
1648     DeleteObject32(hFont);
1649     dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1650     
1651     nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1652     if (nRet == 0) {
1653       dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
1654       break;
1655     }
1656   }
1657   GDI_HEAP_FREE(hMet);
1658   GDI_HEAP_FREE(hLog);
1659   return nRet;
1660 }
1661
1662
1663 /*************************************************************************
1664  *                              EnumFontFamiliesW       [GDI32.82]
1665  */
1666 INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
1667 {
1668   HLOCAL16      hLog;
1669   HLOCAL16      hMet;
1670   HFONT32       hFont;
1671   HFONT32       hOldFont;
1672   LPENUMLOGFONTEX32W    lpEnumLogFont;
1673   LPNEWTEXTMETRICEX32W  lptm;
1674   LPSTR         lpOldName;
1675   int           nRet = 0;
1676   int           i;
1677   LPSTR lpszFamily;
1678   
1679   dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
1680                hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
1681   if (lpEnumFunc == 0) return 0;
1682   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
1683   lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
1684   if (lpEnumLogFont == NULL) {
1685     fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
1686     return 0;
1687   }
1688   hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
1689   lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
1690   if (lptm == NULL) {
1691     GDI_HEAP_FREE(hLog);
1692     fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
1693     return 0;
1694   }
1695   lpOldName = NULL;
1696   lpszFamily = HEAP_strdupWtoA( GetProcessHeap(), 0, lpLF->lfFaceName );
1697   AnsiUpper(lpszFamily);
1698   if (lpLogFontList[0] == NULL) InitFontsList();
1699   for(i = 0; lpLogFontList[i] != NULL; i++) {
1700     /* lfCharSet */
1701     if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1702         if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1703            continue;
1704
1705     /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1706     /* lfFaceName */
1707     if (lpszFamily[0]) {
1708         if (lstrcmpi32A(lpszFamily,lpLogFontList[i]->lfFaceName))
1709            continue;
1710     } else {
1711         if ((lpOldName!=NULL) &&
1712             !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1713            continue;
1714         lpOldName=lpLogFontList[i]->lfFaceName;
1715     }
1716
1717     FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1718     lpEnumLogFont->elfFullName[0] = 0;
1719     lpEnumLogFont->elfStyle[0] = 0;
1720     lpEnumLogFont->elfScript[0] = 0;
1721     hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
1722     hOldFont = SelectObject32(hDC, hFont);
1723     GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
1724     SelectObject32(hDC, hOldFont);
1725     DeleteObject32(hFont);
1726     dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1727     
1728     nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1729     if (nRet == 0) {
1730       dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
1731       break;
1732     }
1733   }
1734   GDI_HEAP_FREE(hMet);
1735   GDI_HEAP_FREE(hLog);
1736   HeapFree( GetProcessHeap(), 0, lpszFamily );
1737   return nRet;
1738 }
1739
1740
1741 /*************************************************************************
1742  *                              GetRasterizerCaps       [GDI.313]
1743  */
1744
1745 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1746 {
1747   /* This is not much more than a dummy */
1748   RASTERIZER_STATUS rs;
1749   
1750   rs.nSize = sizeof(rs);
1751   rs.wFlags = 0;
1752   rs.nLanguageID = 0;
1753   return True;
1754 }
1755
1756 /*************************************************************************
1757  *             GetKerningPairs      [GDI.332]
1758  */
1759 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1760 {
1761     /* This has to be dealt with when proper font handling is in place 
1762      *
1763      * At this time kerning is ignored (set to 0)
1764      */
1765
1766     int i;
1767     fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1768     for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1769     return 0;
1770 }