Release 950727
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <X11/Xatom.h>
13 #include "font.h"
14 #include "metafile.h"
15 #include "wine.h"
16 #include "callback.h"
17 #include "stddebug.h"
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 /***********************************************************************
59  *           FONT_Init
60  */
61 BOOL 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   return TRUE;
91 }
92
93
94 /***********************************************************************
95  *           FONT_TranslateName
96  *
97  * Translate a Windows face name to its X11 equivalent.
98  * This will probably have to be customizable.
99  */
100 static const char *FONT_TranslateName( char *winFaceName )
101 {
102   int i;
103
104   for (i = 1; i < FontSize; i ++)
105     if( !strcmp( winFaceName, FontNames[i].window ) ) {
106       dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
107       return FontNames[i].x11;
108     }
109   return FontNames[0].x11;
110 }
111
112
113 /***********************************************************************
114  *           FONT_MatchFont
115  *
116  * Find a X font matching the logical font.
117  */
118 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
119 {
120     char pattern[100];
121     const char *family, *weight, *charset;
122     char **names;
123     char slant, spacing;
124     int width, height, oldheight, count;
125     XFontStruct * fontStruct;
126     
127     weight = (font->lfWeight > 550) ? "bold" : "medium";
128     slant = font->lfItalic ? 'i' : 'r';
129     height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
130     if (height == 0) height = 120;  /* Default height = 12 */
131     else if (height < 0)
132     {
133           /* If height is negative, it means the height of the characters */
134           /* *without* the internal leading. So we adjust it a bit to     */
135           /* compensate. 5/4 seems to give good results for small fonts.  */
136         height = 10 * (-height * 5 / 4);
137     }
138     else height *= 10;
139     width  = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
140     if (width < 0) {
141         dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
142                       width, font->lfWidth );
143         width = -width;
144     }
145     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
146               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
147     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
148     if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
149     else switch(font->lfPitchAndFamily & 0xf0)
150     {
151     case FF_ROMAN:
152       family = FONT_TranslateName( "roman" );
153       break;
154     case FF_SWISS:
155       family = FONT_TranslateName( "swiss" );
156       break;
157     case FF_MODERN:
158       family = FONT_TranslateName( "modern" );
159       break;
160     case FF_SCRIPT:
161       family = FONT_TranslateName( "script" );
162       break;
163     case FF_DECORATIVE:
164       family = FONT_TranslateName( "decorative" );
165       break;
166     default:
167       family = "*-*";
168       break;
169     }
170     
171     oldheight = height;
172     while (TRUE) {
173             /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
174             if ( width == 0 )
175               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
176                       family, weight, slant, height, spacing, charset);
177             else
178               sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
179                       family, weight, slant, height, spacing, width, charset);
180             dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
181             names = XListFonts( display, pattern, 1, &count );
182             if (count > 0) break;
183             height -= 10;               
184             if (height < 10) {
185                 dprintf_font(stddeb,"*** No match for %s\n", pattern );
186                 if(slant == 'i') {
187                     /* try oblique if no italic font */
188                     slant = 'o';
189                     height = oldheight;
190                     continue;
191                 }
192                 if (spacing == 'm') {
193                     /* If a fixed spacing font could not be found, ignore
194                      * the family */
195                     family = "*-*";
196                     height = oldheight;
197                     continue;
198                 }
199                 return NULL;
200             }
201     }
202     dprintf_font(stddeb,"        Found '%s'\n", *names );
203     fontStruct = XLoadQueryFont( display, *names );
204     XFreeFontNames( names );
205     return fontStruct;
206 }
207
208
209 /***********************************************************************
210  *           FONT_GetMetrics
211  */
212 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
213                       TEXTMETRIC * metrics )
214 {    
215     int average, i, count;
216     unsigned long prop;
217         
218     metrics->tmAscent  = xfont->ascent;
219     metrics->tmDescent = xfont->descent;
220     metrics->tmHeight  = xfont->ascent + xfont->descent;
221
222     metrics->tmInternalLeading  = 0;
223     if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
224         metrics->tmInternalLeading = xfont->ascent - (short)prop;
225     metrics->tmExternalLeading  = 0;
226     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
227     metrics->tmWeight           = logfont->lfWeight;
228     metrics->tmItalic           = logfont->lfItalic;
229     metrics->tmUnderlined       = logfont->lfUnderline;
230     metrics->tmStruckOut        = logfont->lfStrikeOut;
231     metrics->tmFirstChar        = xfont->min_char_or_byte2;
232     metrics->tmLastChar         = xfont->max_char_or_byte2;
233     metrics->tmDefaultChar      = xfont->default_char;
234     metrics->tmBreakChar        = ' ';
235     metrics->tmCharSet          = logfont->lfCharSet;
236     metrics->tmOverhang         = 0;
237     metrics->tmDigitizedAspectX = 1;
238     metrics->tmDigitizedAspectY = 1;
239     metrics->tmPitchAndFamily   = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
240     if (logfont->lfPitchAndFamily & FIXED_PITCH) 
241         metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
242
243     if (!xfont->per_char) average = metrics->tmMaxCharWidth;
244     else
245     {
246         XCharStruct * charPtr = xfont->per_char;
247         average = count = 0;
248         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
249         {
250             if (!CI_NONEXISTCHAR( charPtr ))
251             {
252                 average += charPtr->width;
253                 count++;
254             }
255             charPtr++;
256         }
257         if (count) average = (average + count/2) / count;
258     }
259     metrics->tmAveCharWidth = average;
260 }
261
262 /***********************************************************************
263  *           GetGlyphOutLine    (GDI.309)
264  */
265 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, 
266                       DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2) 
267 {
268     fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
269              hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
270     return (DWORD)-1; /* failure */
271 }
272
273
274 /***********************************************************************
275  *           CreateScalableFontResource    (GDI.310)
276  */
277 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
278                                  LPSTR lpszFontFile, LPSTR lpszCurrentPath )
279 {
280     /* fHidden=1 - only visible for the calling app, read-only, not
281      * enumbered with EnumFonts/EnumFontFamilies
282      * lpszCurrentPath can be NULL
283      */
284     fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
285             fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
286     return FALSE; /* create failed */
287 }
288
289
290 /***********************************************************************
291  *           CreateFontIndirect    (GDI.57)
292  */
293 HFONT CreateFontIndirect( LOGFONT * font )
294 {
295     FONTOBJ * fontPtr;
296     HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
297     if (!hfont) return 0;
298     fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
299     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
300     AnsiLower( fontPtr->logfont.lfFaceName );
301     dprintf_font(stddeb,"CreateFontIndirect(%p); return %04x\n",font,hfont);
302     return hfont;
303 }
304
305
306 /***********************************************************************
307  *           CreateFont    (GDI.56)
308  */
309 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
310                   BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
311                   BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
312                   LPSTR name )
313 {
314     LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
315                     strikeout, charset, outpres, clippres, quality, pitch, };
316     strncpy( logfont.lfFaceName, name, LF_FACESIZE );
317     return CreateFontIndirect( &logfont );
318 }
319
320
321 /***********************************************************************
322  *           FONT_GetObject
323  */
324 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
325 {
326     if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
327     memcpy( buffer, &font->logfont, count );
328     return count;
329 }
330
331
332 /***********************************************************************
333  *           FONT_SelectObject
334  */
335 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
336 {
337     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
338     X_PHYSFONT * stockPtr;
339     HFONT prevHandle = dc->w.hFont;
340     XFontStruct * fontStruct;
341     dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", 
342                      dc, hfont, font);
343       /* Load font if necessary */
344
345     if (!font)
346     {
347         HFONT hnewfont;
348
349         hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
350                               FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
351                               DEFAULT_QUALITY, FF_DONTCARE, "*" );
352         font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
353     }
354
355     if (dc->header.wMagic == METAFILE_DC_MAGIC)
356         return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
357
358     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
359         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
360     else 
361         stockPtr = NULL;
362     
363     if (!stockPtr || !stockPtr->fstruct)
364     {
365         if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
366         {
367               /* If it is not a stock font, we can simply return 0 */
368             if (!stockPtr) return 0;
369               /* Otherwise we must try to find a substitute */
370             dprintf_font(stddeb,"Loading font 'fixed' for %x\n", hfont );
371             font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
372             font->logfont.lfPitchAndFamily |= FIXED_PITCH;
373             fontStruct = XLoadQueryFont( display, "fixed" );
374             if (!fontStruct)
375             {
376                 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
377                 exit( 1 );
378             }
379         }
380     }
381     else
382     {
383         fontStruct = stockPtr->fstruct;
384         dprintf_font(stddeb,
385                      "FONT_SelectObject: Loaded font from cache %x %p\n",
386                      hfont, fontStruct );
387     }   
388
389       /* Free previous font */
390
391     if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
392     {
393         if (dc->u.x.font.fstruct)
394             XFreeFont( display, dc->u.x.font.fstruct );
395     }
396
397       /* Store font */
398
399     dc->w.hFont = hfont;
400     if (stockPtr)
401     {
402         if (!stockPtr->fstruct)
403         {
404             stockPtr->fstruct = fontStruct;
405             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
406         }
407         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
408     }
409     else
410     {
411         dc->u.x.font.fstruct = fontStruct;
412         FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
413     }
414     return prevHandle;
415 }
416
417
418 /***********************************************************************
419  *           GetTextCharacterExtra    (GDI.89)
420  */
421 short GetTextCharacterExtra( HDC hdc )
422 {
423     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
424     if (!dc) return 0;
425     return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
426                  / dc->w.VportExtX );
427 }
428
429
430 /***********************************************************************
431  *           SetTextCharacterExtra    (GDI.8)
432  */
433 short SetTextCharacterExtra( HDC hdc, short extra )
434 {
435     short prev;
436     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
437     if (!dc) return 0;
438     extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;    
439     prev = dc->w.charExtra;
440     dc->w.charExtra = abs(extra);
441     return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
442 }
443
444
445 /***********************************************************************
446  *           SetTextJustification    (GDI.10)
447  */
448 short SetTextJustification( HDC hdc, short extra, short breaks )
449 {
450     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
451     if (!dc) return 0;
452
453     extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
454     if (!extra) breaks = 0;
455     dc->w.breakTotalExtra = extra;
456     dc->w.breakCount = breaks;
457     if (breaks)
458     {   
459         dc->w.breakExtra = extra / breaks;
460         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
461     }
462     else
463     {
464         dc->w.breakExtra = 0;
465         dc->w.breakRem   = 0;
466     }
467     return 1;
468 }
469
470
471 /***********************************************************************
472  *           GetTextFace    (GDI.92)
473  */
474 INT GetTextFace( HDC hdc, INT count, LPSTR name )
475 {
476     FONTOBJ *font;
477
478     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
479     if (!dc) return 0;
480     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
481         return 0;
482     strncpy( name, font->logfont.lfFaceName, count );
483     name[count-1] = '\0';
484     return strlen(name);
485 }
486
487
488 /***********************************************************************
489  *           GetTextExtent    (GDI.91)
490  */
491 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
492 {
493     SIZE size;
494     if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
495     return MAKELONG( size.cx, size.cy );
496 }
497
498
499 /***********************************************************************
500  *           GetTextExtentPoint    (GDI.471)
501  */
502 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
503 {
504     int dir, ascent, descent;
505     XCharStruct info;
506
507     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
508     if (!dc) return FALSE;
509     XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
510                   &ascent, &descent, &info );
511     size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
512                     * dc->w.WndExtX / dc->w.VportExtX);
513     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
514                     * dc->w.WndExtY / dc->w.VportExtY);
515
516     dprintf_font(stddeb,"GetTextExtentPoint(%d '%*.*s' %d %p): returning %d,%d\n",
517             hdc, count, count, str, count, size, size->cx, size->cy );
518     return TRUE;
519 }
520
521
522 /***********************************************************************
523  *           GetTextMetrics    (GDI.93)
524  */
525 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
526 {
527     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
528     if (!dc) return FALSE;
529     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
530
531     metrics->tmAscent  = abs( metrics->tmAscent
532                               * dc->w.WndExtY / dc->w.VportExtY );
533     metrics->tmDescent = abs( metrics->tmDescent
534                               * dc->w.WndExtY / dc->w.VportExtY );
535     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
536     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
537                                       * dc->w.WndExtY / dc->w.VportExtY );
538     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
539                                       * dc->w.WndExtY / dc->w.VportExtY );
540     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
541                                       * dc->w.WndExtX / dc->w.VportExtX );
542     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
543                                       * dc->w.WndExtX / dc->w.VportExtX );
544     return TRUE;
545 }
546
547
548 /***********************************************************************
549  *           SetMapperFlags    (GDI.349)
550  */
551 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
552 {
553     dprintf_font(stdnimp,"SetmapperFlags(%04X, %08lX) // Empty Stub !\n", 
554                  hDC, dwFlag); 
555     return 0L;
556 }
557
558  
559 /***********************************************************************/
560
561
562 /***********************************************************************
563  *           GetCharWidth    (GDI.350)
564  */
565 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
566 {
567     int i, j;
568     XFontStruct *xfont;
569     XCharStruct *cs, *def;
570
571     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
572     if (!dc) return FALSE;
573     xfont = dc->u.x.font.fstruct;
574     
575     /* fixed font? */
576     if (xfont->per_char == NULL)
577     {
578         for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
579             *(lpBuffer + j) = xfont->max_bounds.width;
580         return TRUE;
581     }
582
583     CI_GET_DEFAULT_INFO(xfont, def);
584         
585     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
586     {
587         CI_GET_CHAR_INFO(xfont, i, def, cs);
588         *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
589         if (*(lpBuffer + j) < 0)
590             *(lpBuffer + j) = 0;
591     }
592     return TRUE;
593 }
594
595
596 /***********************************************************************
597  *           AddFontResource    (GDI.119)
598  */
599 int AddFontResource( LPSTR str )
600 {
601     fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
602     return 1;
603 }
604
605
606 /***********************************************************************
607  *           RemoveFontResource    (GDI.136)
608  */
609 BOOL RemoveFontResource( LPSTR str )
610 {
611     fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
612     return TRUE;
613 }
614
615
616 /*************************************************************************
617  *                              ParseFontParms          [internal]
618  */
619 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
620 {
621         int     i;
622         dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n", 
623                         lpFont, wParmsNo, lpRetStr, wMaxSiz);
624         if (lpFont == NULL) return 0;
625         if (lpRetStr == NULL) return 0;
626         for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
627                 if (*lpFont == '-') i++;
628                 lpFont++;
629                 }
630         if (i == wParmsNo) {
631                 if (*lpFont == '-') lpFont++;
632                 wMaxSiz--;
633                 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
634                         *(lpRetStr + i) = *lpFont++;
635                 *(lpRetStr + i) = '\0';
636                 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
637                 return i;
638                 }
639         else
640                 lpRetStr[0] = '\0';
641         return 0;
642 }
643
644
645 /*************************************************************************
646  *                              InitFontsList           [internal]
647  */
648
649 static int logfcmp(const void *a,const void *b) 
650 {
651   return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
652 }
653
654 void InitFontsList(void)
655 {
656   char  str[32];
657   char  pattern[100];
658   char  *family, *weight, *charset;
659   char  **names;
660   char  slant, spacing;
661   int   i, count;
662   LPLOGFONT lpNewFont;
663   weight = "medium";
664   slant = 'r';
665   spacing = '*';
666   charset = "*";
667   family = "*-*";
668   dprintf_font(stddeb,"InitFontsList !\n");
669   sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
670           family, weight, slant, spacing, charset);
671   names = XListFonts( display, pattern, MAX_FONTS, &count );
672   dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
673   for (i = 0; i < count; i++) {
674     lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
675     if (lpNewFont == NULL) {
676       dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
677       break;
678     }
679     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
680     ParseFontParms(names[i], 2, str, sizeof(str));
681     if (strcmp(str, "fixed") == 0) strcat(str, "sys");
682     AnsiUpper(str);
683     strcpy(lpNewFont->lfFaceName, str);
684     ParseFontParms(names[i], 8, str, sizeof(str));
685     lpNewFont->lfHeight = atoi(str) / 10;
686     ParseFontParms(names[i], 12, str, sizeof(str));
687     lpNewFont->lfWidth = atoi(str) / 10;
688     lpNewFont->lfEscapement = 0;
689     lpNewFont->lfOrientation = 0;
690     lpNewFont->lfWeight = FW_REGULAR;
691     lpNewFont->lfItalic = 0;
692     lpNewFont->lfUnderline = 0;
693     lpNewFont->lfStrikeOut = 0;
694     ParseFontParms(names[i], 13, str, sizeof(str));
695     if (strcmp(str, "iso8859") == 0)  {
696       lpNewFont->lfCharSet = ANSI_CHARSET;
697     } else  {
698       lpNewFont->lfCharSet = OEM_CHARSET;
699     }
700     lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
701     lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
702     lpNewFont->lfQuality = DEFAULT_QUALITY;
703     ParseFontParms(names[i], 11, str, sizeof(str));
704     switch(str[0]) {
705      case 'p':
706       lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
707       break;
708      case 'm':
709       lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
710       break;
711      default:
712       lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
713       break;
714     }
715     dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
716     dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
717     dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
718     lpLogFontList[i] = lpNewFont;
719     lpLogFontList[i+1] = NULL;
720   }
721   qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
722   XFreeFontNames(names);
723 }
724
725
726 /*************************************************************************
727  *                              EnumFonts                       [GDI.70]
728  */
729 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
730 {
731   HANDLE       hLog;
732   HANDLE       hMet;
733   HFONT        hFont;
734   HFONT        hOldFont;
735   LPLOGFONT    lpLogFont;
736   LPTEXTMETRIC lptm;
737   LPSTR        lpOldName;
738   char         FaceName[LF_FACESIZE];
739   int          nRet = 0;
740   int          i;
741   
742   dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %08lx, %p)\n", 
743                hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
744   if (lpEnumFunc == 0) return 0;
745   hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
746   lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
747   if (lpLogFont == NULL) {
748     fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
749     return 0;
750   }
751   hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
752   lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
753   if (lptm == NULL) {
754     GDI_HEAP_FREE(hLog);
755     fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
756     return 0;
757   }
758   if (lpFaceName != NULL) {
759     strcpy(FaceName, lpFaceName);
760     AnsiUpper(FaceName);
761   } 
762   lpOldName = NULL;
763   
764   if (lpLogFontList[0] == NULL) InitFontsList();
765   for(i = 0; lpLogFontList[i] != NULL; i++) {
766     if (lpFaceName == NULL) {
767       if (lpOldName != NULL) {
768         if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
769       }
770       lpOldName = lpLogFontList[i]->lfFaceName;
771     } else {
772       if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
773     }
774     dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
775     dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
776     memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
777     hFont = CreateFontIndirect(lpLogFont);
778     hOldFont = SelectObject(hDC, hFont);
779     GetTextMetrics(hDC, lptm);
780     SelectObject(hDC, hOldFont);
781     DeleteObject(hFont);
782     dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
783     nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
784                              GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
785     if (nRet == 0) {
786       dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
787       break;
788     }
789   }
790   GDI_HEAP_FREE(hMet);
791   GDI_HEAP_FREE(hLog);
792   return nRet;
793 }
794
795
796 /*************************************************************************
797  *                              EnumFontFamilies        [GDI.330]
798  */
799 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
800 {
801   HANDLE        hLog;
802   HANDLE        hMet;
803   HFONT         hFont;
804   HFONT         hOldFont;
805   LPENUMLOGFONT lpEnumLogFont;
806   LPTEXTMETRIC  lptm;
807   LPSTR         lpOldName;
808   char          FaceName[LF_FACESIZE];
809   int           nRet = 0;
810   int           i;
811   
812   dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %08lx, %p)\n",
813                hDC, lpszFamily, lpEnumFunc, lpData);
814   if (lpEnumFunc == 0) return 0;
815   hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
816   lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
817   if (lpEnumLogFont == NULL) {
818     fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
819     return 0;
820   }
821   hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
822   lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
823   if (lptm == NULL) {
824     GDI_HEAP_FREE(hLog);
825     fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
826     return 0;
827   }
828   lpOldName = NULL;
829   if (lpszFamily != NULL) {
830     strcpy(FaceName, lpszFamily);
831     AnsiUpper(FaceName);
832   }
833   if (lpLogFontList[0] == NULL) InitFontsList();
834   for(i = 0; lpLogFontList[i] != NULL; i++) {
835     if (lpszFamily == NULL) {
836       if (lpOldName != NULL) {
837         if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
838       }
839       lpOldName = lpLogFontList[i]->lfFaceName;
840     } else {
841       if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
842     }
843     memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
844     strcpy(lpEnumLogFont->elfFullName,"");
845     strcpy(lpEnumLogFont->elfStyle,"");
846     hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
847     hOldFont = SelectObject(hDC, hFont);
848     GetTextMetrics(hDC, lptm);
849     SelectObject(hDC, hOldFont);
850     DeleteObject(hFont);
851     dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
852     
853     nRet = CallEnumFontFamProc( lpEnumFunc,
854                                GDI_HEAP_SEG_ADDR(hLog),
855                                GDI_HEAP_SEG_ADDR(hMet),
856                                0, (LONG)lpData );
857     if (nRet == 0) {
858       dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
859       break;
860     }
861   }
862   GDI_HEAP_FREE(hMet);
863   GDI_HEAP_FREE(hLog);
864   return nRet;
865 }
866
867 /*************************************************************************
868  *                              GetRasterizerCaps       [GDI.313]
869  */
870
871 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
872 {
873   /* This is not much more than a dummy */
874   RASTERIZER_STATUS rs;
875   
876   rs.nSize = sizeof(rs);
877   rs.wFlags = 0;
878   rs.nLanguageID = 0;
879   return True;
880 }
881
882 /*************************************************************************
883  *             GetKerningPairs      [GDI.332]
884  *  FIXME: The last parameter is actually LPKERNINGPAIR
885  */
886 int GetKerningPairs(WORD hDC,int cBufLen,LPVOID lpKerningPairs)
887 {
888         /* Wine fonts are ugly and don't support kerning :) */
889         return 0;
890 }