Release 941107
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <X11/Xatom.h>
13 #include "user.h"
14 #include "gdi.h"
15 #include "stddebug.h"
16 /* #define DEBUG_FONT /* */
17 /* #undef  DEBUG_FONT /* */
18 #include "debug.h"
19
20 #define MAX_FONTS       256
21 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
22
23
24 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
25                              (((cs)->rbearing|(cs)->lbearing| \
26                                (cs)->ascent|(cs)->descent) == 0))
27
28 /* 
29  * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
30  * character.  If the character is in the column and exists, then return the
31  * appropriate metrics (note that fonts with common per-character metrics will
32  * return min_bounds).  If none of these hold true, try again with the default
33  * char.
34  */
35 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
36 { \
37     cs = def; \
38     if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
39         if (fs->per_char == NULL) { \
40             cs = &fs->min_bounds; \
41         } else { \
42             cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
43             if (CI_NONEXISTCHAR(cs)) cs = def; \
44         } \
45     } \
46 }
47
48 #define CI_GET_DEFAULT_INFO(fs,cs) \
49   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
50
51 struct FontStructure {
52         char *window;
53         char *x11;
54 } FontNames[32];
55 int FontSize;
56
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
58  *           Font_Init
59  */
60
61 void Font_Init( void )
62 {
63   char  temp[1024];
64   LPSTR ptr;
65   int i;
66
67   if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
68     for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
69       if( strcmp( ptr, "default" ) )
70         FontNames[i++].window = strdup( ptr );
71     FontSize = i;
72
73     for( i = 1; i < FontSize; i++ ) {
74       GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
75       FontNames[i].x11 = strdup( temp );
76     }
77     GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
78     FontNames[0].x11 = strdup( temp );
79
80   } else {
81     FontNames[0].window = NULL; FontNames[0].x11 = "bitstream-courier";
82     FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
83     FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
84     FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
85     FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
86     FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
87     FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
88     FontSize = 7;
89   }
90 }
91
92 /***********************************************************************
93  *           FONT_TranslateName
94  *
95  * Translate a Windows face name to its X11 equivalent.
96  * This will probably have to be customizable.
97  */
98 static const char *FONT_TranslateName( char *winFaceName )
99 {
100   int i;
101
102   for (i = 1; i < FontSize; i ++)
103     if( !strcmp( winFaceName, FontNames[i].window ) ) {
104       dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
105       return FontNames[i].x11;
106     }
107   return FontNames[0].x11;
108 }
109
110
111 /***********************************************************************
112  *           FONT_MatchFont
113  *
114  * Find a X font matching the logical font.
115  */
116 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
117 {
118     char pattern[100];
119     const char *family, *weight, *charset;
120     char **names;
121     char slant, spacing;
122     int width, height, count;
123     XFontStruct * fontStruct;
124     
125     weight = (font->lfWeight > 550) ? "bold" : "medium";
126     slant = font->lfItalic ? 'i' : 'r';
127     height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
128     if (height == 0) height = 120;  /* Default height = 12 */
129     else if (height < 0)
130     {
131           /* If height is negative, it means the height of the characters */
132           /* *without* the internal leading. So we adjust it a bit to     */
133           /* compensate. 5/4 seems to give good results for small fonts.  */
134         height = 10 * (-height * 5 / 4);
135     }
136     else height *= 10;
137     width  = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
138     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
139               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
140     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
141     if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
142     else switch(font->lfPitchAndFamily & 0xf0)
143     {
144     case FF_ROMAN:
145       family = FONT_TranslateName( "roman" );
146       break;
147     case FF_SWISS:
148       family = FONT_TranslateName( "swiss" );
149       break;
150     case FF_MODERN:
151       family = FONT_TranslateName( "modern" );
152       break;
153     case FF_SCRIPT:
154       family = FONT_TranslateName( "script" );
155       break;
156     case FF_DECORATIVE:
157       family = FONT_TranslateName( "decorative" );
158       break;
159     default:
160       family = FontNames[0].x11;
161       break;
162     }
163     
164         while (TRUE) {
165             /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
166             if ( width == 0 )
167               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
168                       family, weight, slant, height, spacing, charset);
169             else
170               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
171                       family, weight, slant, height, spacing, width, charset);
172             dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
173             names = XListFonts( display, pattern, 1, &count );
174             if (count > 0) break;
175             height -= 10;               
176             if (height < 10) {
177                 dprintf_font(stddeb,"*** No match for %s\n", pattern );
178                 return NULL;
179             }
180         }
181     dprintf_font(stddeb,"        Found '%s'\n", *names );
182     fontStruct = XLoadQueryFont( display, *names );
183     XFreeFontNames( names );
184     return fontStruct;
185 }
186
187
188 /***********************************************************************
189  *           FONT_GetMetrics
190  */
191 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
192                       TEXTMETRIC * metrics )
193 {    
194     int average, i, count;
195     unsigned long prop;
196         
197     metrics->tmAscent  = xfont->ascent;
198     metrics->tmDescent = xfont->descent;
199     metrics->tmHeight  = xfont->ascent + xfont->descent;
200
201     metrics->tmInternalLeading  = 0;
202     if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
203         metrics->tmInternalLeading = xfont->ascent - (short)prop;
204     metrics->tmExternalLeading  = 0;
205     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
206     metrics->tmWeight           = logfont->lfWeight;
207     metrics->tmItalic           = logfont->lfItalic;
208     metrics->tmUnderlined       = logfont->lfUnderline;
209     metrics->tmStruckOut        = logfont->lfStrikeOut;
210     metrics->tmFirstChar        = xfont->min_char_or_byte2;
211     metrics->tmLastChar         = xfont->max_char_or_byte2;
212     metrics->tmDefaultChar      = xfont->default_char;
213     metrics->tmBreakChar        = ' ';
214     metrics->tmPitchAndFamily   = logfont->lfPitchAndFamily;
215     metrics->tmCharSet          = logfont->lfCharSet;
216     metrics->tmOverhang         = 0;
217     metrics->tmDigitizedAspectX = 1;
218     metrics->tmDigitizedAspectY = 1;
219
220     if (!xfont->per_char) average = metrics->tmMaxCharWidth;
221     else
222     {
223         XCharStruct * charPtr = xfont->per_char;
224         average = count = 0;
225         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
226         {
227             if (!CI_NONEXISTCHAR( charPtr ))
228             {
229                 average += charPtr->width;
230                 count++;
231             }
232             charPtr++;
233         }
234         if (count) average = (average + count/2) / count;
235     }
236     metrics->tmAveCharWidth = average;
237 }
238
239
240 /***********************************************************************
241  *           CreateFontIndirect    (GDI.57)
242  */
243 HFONT CreateFontIndirect( LOGFONT * font )
244 {
245     FONTOBJ * fontPtr;
246     HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
247     if (!hfont) return 0;
248     fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
249     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
250     AnsiLower( fontPtr->logfont.lfFaceName );
251     dprintf_font(stddeb,"CreateFontIndirect(%08X); return %04X\n",font,hfont);
252     return hfont;
253 }
254
255
256 /***********************************************************************
257  *           CreateFont    (GDI.56)
258  */
259 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
260                   BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
261                   BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
262                   LPSTR name )
263 {
264     LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
265                     strikeout, charset, outpres, clippres, quality, pitch, };
266     strncpy( logfont.lfFaceName, name, LF_FACESIZE );
267     return CreateFontIndirect( &logfont );
268 }
269
270
271 /***********************************************************************
272  *           FONT_GetObject
273  */
274 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
275 {
276     if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
277     memcpy( buffer, &font->logfont, count );
278     return count;
279 }
280
281
282 /***********************************************************************
283  *           FONT_SelectObject
284  */
285 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
286 {
287     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
288     X_PHYSFONT * stockPtr;
289     HFONT prevHandle = dc->w.hFont;
290     XFontStruct * fontStruct;
291     dprintf_font(stddeb,"FONT_SelectObject(%04X, %04X, %08X); !\n", 
292                      dc, hfont, font);
293       /* Load font if necessary */
294
295     if (!font)
296     {
297         HFONT hnewfont;
298
299         hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
300                               FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
301                               DEFAULT_QUALITY, FF_DONTCARE, "*" );
302         font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
303     }
304
305     if (dc->header.wMagic == METAFILE_DC_MAGIC)
306         return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
307
308     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
309         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
310     else 
311         stockPtr = NULL;
312     
313     if (!stockPtr || !stockPtr->fstruct)
314     {
315         fontStruct = FONT_MatchFont( &font->logfont, dc );
316     }
317     else
318     {
319         fontStruct = stockPtr->fstruct;
320         dprintf_font(stddeb, 
321                      "FONT_SelectObject: Loaded font from cache %x %p\n",
322                      hfont, fontStruct );
323     }   
324     if (!fontStruct) return 0;
325
326       /* Free previous font */
327
328     if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
329     {
330         if (dc->u.x.font.fstruct)
331             XFreeFont( display, dc->u.x.font.fstruct );
332     }
333
334       /* Store font */
335
336     dc->w.hFont = hfont;
337     if (stockPtr)
338     {
339         if (!stockPtr->fstruct)
340         {
341             stockPtr->fstruct = fontStruct;
342             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
343         }
344         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
345     }
346     else
347     {
348         dc->u.x.font.fstruct = fontStruct;
349         FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
350     }
351     return prevHandle;
352 }
353
354
355 /***********************************************************************
356  *           GetTextCharacterExtra    (GDI.89)
357  */
358 short GetTextCharacterExtra( HDC hdc )
359 {
360     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
361     if (!dc) return 0;
362     return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
363                  / dc->w.VportExtX );
364 }
365
366
367 /***********************************************************************
368  *           SetTextCharacterExtra    (GDI.8)
369  */
370 short SetTextCharacterExtra( HDC hdc, short extra )
371 {
372     short prev;
373     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
374     if (!dc) return 0;
375     extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;    
376     prev = dc->w.charExtra;
377     dc->w.charExtra = abs(extra);
378     return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
379 }
380
381
382 /***********************************************************************
383  *           SetTextJustification    (GDI.10)
384  */
385 short SetTextJustification( HDC hdc, short extra, short breaks )
386 {
387     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
388     if (!dc) return 0;
389
390     extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
391     if (!extra) breaks = 0;
392     dc->w.breakTotalExtra = extra;
393     dc->w.breakCount = breaks;
394     if (breaks)
395     {   
396         dc->w.breakExtra = extra / breaks;
397         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
398     }
399     else
400     {
401         dc->w.breakExtra = 0;
402         dc->w.breakRem   = 0;
403     }
404     return 1;
405 }
406
407
408 /***********************************************************************
409  *           GetTextFace    (GDI.92)
410  */
411 INT GetTextFace( HDC hdc, INT count, LPSTR name )
412 {
413     FONTOBJ *font;
414
415     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
416     if (!dc) return 0;
417     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
418         return 0;
419     strncpy( name, font->logfont.lfFaceName, count );
420     name[count-1] = '\0';
421     return strlen(name);
422 }
423
424
425 /***********************************************************************
426  *           GetTextExtent    (GDI.91)
427  */
428 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
429 {
430     SIZE size;
431     if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
432     return size.cx | (size.cy << 16);
433 }
434
435
436 /***********************************************************************
437  *           GetTextExtentPoint    (GDI.471)
438  */
439 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
440 {
441     int dir, ascent, descent;
442     XCharStruct info;
443
444     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
445     if (!dc) return FALSE;
446     XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
447                   &ascent, &descent, &info );
448     size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
449                     * dc->w.WndExtX / dc->w.VportExtX);
450     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
451                     * dc->w.WndExtY / dc->w.VportExtY);
452
453     dprintf_font(stddeb,"GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
454             hdc, str, count, size, size->cx, size->cy );
455     return TRUE;
456 }
457
458
459 /***********************************************************************
460  *           GetTextMetrics    (GDI.93)
461  */
462 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
463 {
464     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
465     if (!dc) return FALSE;
466     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
467
468     metrics->tmAscent  = abs( metrics->tmAscent
469                               * dc->w.WndExtY / dc->w.VportExtY );
470     metrics->tmDescent = abs( metrics->tmDescent
471                               * dc->w.WndExtY / dc->w.VportExtY );
472     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
473     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
474                                       * dc->w.WndExtY / dc->w.VportExtY );
475     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
476                                       * dc->w.WndExtY / dc->w.VportExtY );
477     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
478                                       * dc->w.WndExtX / dc->w.VportExtX );
479     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
480                                       * dc->w.WndExtX / dc->w.VportExtX );
481     return TRUE;
482 }
483
484
485 /***********************************************************************
486  *           SetMapperFlags    (GDI.349)
487  */
488 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
489 {
490     dprintf_font(stdnimp,"SetmapperFlags(%04X, %08X) // Empty Stub !\n", 
491                  hDC, dwFlag); 
492     return 0L;
493 }
494
495  
496 /***********************************************************************/
497
498
499 /***********************************************************************
500  *           GetCharWidth    (GDI.350)
501  */
502 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
503 {
504     int i, j;
505     XFontStruct *xfont;
506     XCharStruct *cs, *def;
507
508     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
509     if (!dc) return FALSE;
510     xfont = dc->u.x.font.fstruct;
511     
512     /* fixed font? */
513     if (xfont->per_char == NULL)
514     {
515         for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
516             *(lpBuffer + j) = xfont->max_bounds.width;
517         return TRUE;
518     }
519
520     CI_GET_DEFAULT_INFO(xfont, def);
521         
522     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
523     {
524         CI_GET_CHAR_INFO(xfont, i, def, cs);
525         *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
526         if (*(lpBuffer + j) < 0)
527             *(lpBuffer + j) = 0;
528     }
529     return TRUE;
530 }
531
532
533 /***********************************************************************
534  *           AddFontResource    (GDI.119)
535  */
536 int AddFontResource( LPSTR str )
537 {
538     fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
539     return 1;
540 }
541
542
543 /***********************************************************************
544  *           RemoveFontResource    (GDI.136)
545  */
546 BOOL RemoveFontResource( LPSTR str )
547 {
548     fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
549     return TRUE;
550 }
551
552
553 /*************************************************************************
554  *                              ParseFontParms          [internal]
555  */
556 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
557 {
558         int     i, j;
559         dprintf_font(stddeb,"ParseFontParms('%s', %d, %08X, %d);\n", 
560                         lpFont, wParmsNo, lpRetStr, wMaxSiz);
561         if (lpFont == NULL) return 0;
562         if (lpRetStr == NULL) return 0;
563         for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
564                 if (*lpFont == '-') i++;
565                 lpFont++;
566                 }
567         if (i == wParmsNo) {
568                 if (*lpFont == '-') lpFont++;
569                 wMaxSiz--;
570                 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
571                         *(lpRetStr + i) = *lpFont++;
572                 *(lpRetStr + i) = '\0';
573                 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
574                 return i;
575                 }
576         else
577                 lpRetStr[0] = '\0';
578         return 0;
579 }
580
581
582 /*************************************************************************
583  *                              InitFontsList           [internal]
584  */
585 void InitFontsList()
586 {
587     char        str[32];
588     char        pattern[100];
589     char        *family, *weight, *charset;
590         char    **names;
591     char        slant, spacing;
592     int         i, width, count;
593         LPLOGFONT       lpNewFont;
594     weight = "medium";
595     slant = 'r';
596     spacing = '*';
597     charset = "*";
598     family = "*-*";
599     dprintf_font(stddeb,"InitFontsList !\n");
600     sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
601               family, weight, slant, spacing, charset);
602     names = XListFonts( display, pattern, MAX_FONTS, &count );
603     dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
604         for (i = 0; i < count; i++) {
605                 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
606                 if (lpNewFont == NULL) {
607                         dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
608                         break;
609                         }
610                 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
611                 ParseFontParms(names[i], 2, str, sizeof(str));
612                 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
613                 AnsiUpper(str);
614                 strcpy(lpNewFont->lfFaceName, str);
615                 ParseFontParms(names[i], 7, str, sizeof(str));
616                 lpNewFont->lfHeight = atoi(str) / 10;
617                 ParseFontParms(names[i], 12, str, sizeof(str));
618                 lpNewFont->lfWidth = atoi(str) / 10;
619                 lpNewFont->lfEscapement = 0;
620                 lpNewFont->lfOrientation = 0;
621                 lpNewFont->lfWeight = FW_REGULAR;
622                 lpNewFont->lfItalic = 0;
623                 lpNewFont->lfUnderline = 0;
624                 lpNewFont->lfStrikeOut = 0;
625                 ParseFontParms(names[i], 13, str, sizeof(str));
626                 if (strcmp(str, "iso8859") == 0)
627                         lpNewFont->lfCharSet = ANSI_CHARSET;
628                 else
629                         lpNewFont->lfCharSet = OEM_CHARSET;
630                 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
631                 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
632                 lpNewFont->lfQuality = DEFAULT_QUALITY;
633                 ParseFontParms(names[i], 11, str, sizeof(str));
634                 switch(str[0]) {
635                         case 'p':
636                                 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
637                                 break;
638                         case 'm':
639                                 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
640                                 break;
641                         default:
642                                 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
643                                 break;
644                         }
645                 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
646                 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
647                 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
648                 lpLogFontList[i] = lpNewFont;
649                 lpLogFontList[i+1] = NULL;
650                 }
651     XFreeFontNames(names);
652 }
653
654
655 /*************************************************************************
656  *                              EnumFonts                       [GDI.70]
657  */
658 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
659 {
660         HANDLE                  hLog;
661         HANDLE                  hMet;
662         HFONT                   hFont;
663         HFONT                   hOldFont;
664         LPLOGFONT               lpLogFont;
665         LPTEXTMETRIC    lptm;
666         LPSTR                   lpFaceList[MAX_FONTS];
667         char                    FaceName[LF_FACESIZE];
668         int                             nRet;
669         int                             j, i = 0;
670
671         dprintf_font(stddeb,"EnumFonts(%04X, %08X='%s', %08X, %08X)\n", 
672                 hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
673         if (lpEnumFunc == NULL) return 0;
674         hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
675         lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
676         if (lpLogFont == NULL) {
677                 dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
678                 return 0;
679                 }
680         hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
681         lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
682         if (lptm == NULL) {
683                 USER_HEAP_FREE(hLog);
684                 dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
685                 return 0;
686                 }
687         if (lpFaceName != NULL) {
688                 strcpy(FaceName, lpFaceName);
689                 AnsiUpper(FaceName);
690                 }
691         if (lpLogFontList[0] == NULL) InitFontsList();
692         memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
693         while (TRUE) {
694                 if (lpLogFontList[i] == NULL) break;
695                 if (lpFaceName == NULL) {
696                         for (j = 0; j < MAX_FONTS; j++) {
697                                 if (lpFaceList[j] == NULL) break;
698                                 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
699                                         i++; j = 0;
700                                         if (lpLogFontList[i] == NULL) break;
701                                         }
702                                 }
703                         if (lpLogFontList[i] == NULL) break;
704                         lpFaceList[j] = lpLogFontList[i]->lfFaceName;
705                         dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
706                         }
707                 else {
708                         while(lpLogFontList[i] != NULL) {
709                                 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
710                                 i++;
711                                 }
712                         if (lpLogFontList[i] == NULL) break;
713                         }
714                 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
715                 hFont = CreateFontIndirect(lpLogFont);
716                 hOldFont = SelectObject(hDC, hFont);
717                 GetTextMetrics(hDC, lptm);
718                 SelectObject(hDC, hOldFont);
719                 DeleteObject(hFont);
720                 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
721
722 #ifdef WINELIB
723                 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
724 #else
725                 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
726                                         2, (int)lptm, 0, (int)0, 2, (int)lpData);
727 #endif
728                 if (nRet == 0) {
729                         dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
730                         break;
731                         }
732                 }
733         USER_HEAP_FREE(hMet);
734         USER_HEAP_FREE(hLog);
735         return 0;
736 }
737
738
739 /*************************************************************************
740  *                              EnumFontFamilies        [GDI.330]
741  */
742 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
743 {
744         HANDLE                  hLog;
745         HANDLE                  hMet;
746         HFONT                   hFont;
747         HFONT                   hOldFont;
748         LPLOGFONT               lpLogFont;
749         LPTEXTMETRIC    lptm;
750         LPSTR                   lpFaceList[MAX_FONTS];
751         char                    FaceName[LF_FACESIZE];
752         int                             nRet;
753         int                             j, i = 0;
754
755         dprintf_font(stddeb,"EnumFontFamilies(%04X, %08X, %08X, %08X)\n", 
756                                         hDC, lpszFamily, lpEnumFunc, lpData);
757         if (lpEnumFunc == NULL) return 0;
758         hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
759         lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
760         if (lpLogFont == NULL) {
761                 dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
762                 return 0;
763                 }
764         hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
765         lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
766         if (lptm == NULL) {
767                 USER_HEAP_FREE(hLog);
768                 dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
769                 return 0;
770                 }
771         if (lpszFamily != NULL) {
772                 strcpy(FaceName, lpszFamily);
773                 AnsiUpper(FaceName);
774                 }
775         if (lpLogFontList[0] == NULL) InitFontsList();
776         memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
777         while (TRUE) {
778                 if (lpLogFontList[i] == NULL) break;
779                 if (lpszFamily == NULL) {
780                         if (lpLogFontList[i] == NULL) break;
781                         for (j = 0; j < MAX_FONTS; j++) {
782                                 if (lpFaceList[j] == NULL) break;
783                                 if (lpLogFontList[i] == NULL) break;
784                                 if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
785                                         i++; j = 0;
786                                         }
787                                 }
788                         if (lpLogFontList[i] == NULL) break;
789                         lpFaceList[j] = lpLogFontList[i]->lfFaceName;
790                         dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
791                         }
792                 else {
793                         while(lpLogFontList[i] != NULL) {
794                                 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
795                                 i++;
796                                 }
797                         if (lpLogFontList[i] == NULL) break;
798                         }
799                 memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
800                 hFont = CreateFontIndirect(lpLogFont);
801                 hOldFont = SelectObject(hDC, hFont);
802                 GetTextMetrics(hDC, lptm);
803                 SelectObject(hDC, hOldFont);
804                 DeleteObject(hFont);
805                 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
806
807 #ifdef WINELIB
808                 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
809 #else
810                 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
811                                         2, (int)lptm, 0, (int)0, 2, (int)lpData);
812 #endif
813                 if (nRet == 0) {
814                         dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
815                         break;
816                         }
817                 }
818         USER_HEAP_FREE(hMet);
819         USER_HEAP_FREE(hLog);
820         return 0;
821 }
822
823
824