Release 960225
[wine.git] / objects / font.c
blobbbef8f6578675498850148824a589cbbfafd9d33
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <X11/Xatom.h>
12 #include "font.h"
13 #include "metafile.h"
14 #include "callback.h"
15 #include "options.h"
16 #include "xmalloc.h"
17 #include "stddebug.h"
18 #include "debug.h"
20 #define MAX_FONTS 256
21 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
24 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
25 (((cs)->rbearing|(cs)->lbearing| \
26 (cs)->ascent|(cs)->descent) == 0))
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.
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 } \
48 #define CI_GET_DEFAULT_INFO(fs,cs) \
49 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
51 struct FontStructure {
52 char *window;
53 char *x11;
54 } FontNames[32];
55 int FontSize;
58 /***********************************************************************
59 * FONT_Init
61 BOOL FONT_Init( void )
63 char temp[1024];
64 LPSTR ptr;
65 int i;
67 if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
69 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
70 if( strcmp( ptr, "default" ) )
71 FontNames[i++].window = xstrdup( ptr );
72 FontSize = i;
74 for( i = 1; i < FontSize; i++ )
76 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
77 temp, sizeof(temp) );
78 FontNames[i].x11 = xstrdup( temp );
80 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
81 FontNames[0].x11 = xstrdup( temp );
83 } else {
84 FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
85 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
86 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
87 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
88 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
89 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
90 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
91 FontSize = 7;
93 return TRUE;
97 /***********************************************************************
98 * FONT_TranslateName
100 * Translate a Windows face name to its X11 equivalent.
101 * This will probably have to be customizable.
103 static const char *FONT_TranslateName( char *winFaceName )
105 int i;
107 for (i = 1; i < FontSize; i ++)
108 if( !strcmp( winFaceName, FontNames[i].window ) ) {
109 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
110 return FontNames[i].x11;
112 return FontNames[0].x11;
116 /***********************************************************************
117 * FONT_MatchFont
119 * Find a X font matching the logical font.
121 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
123 char pattern[100];
124 const char *family, *weight, *charset;
125 char **names;
126 char slant, oldspacing, spacing;
127 int width, height, oldheight, count;
128 XFontStruct * fontStruct;
130 dprintf_font(stddeb,
131 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
132 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
133 weight = (font->lfWeight > 550) ? "bold" : "medium";
134 slant = font->lfItalic ? 'i' : 'r';
135 if (font->lfHeight == -1)
136 height = 0;
137 else
138 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
139 if (height == 0) height = 120; /* Default height = 12 */
140 else if (height < 0)
142 /* If height is negative, it means the height of the characters */
143 /* *without* the internal leading. So we adjust it a bit to */
144 /* compensate. 5/4 seems to give good results for small fonts. */
145 height = 10 * (-height * 8 / 7);
147 else height *= 10;
148 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
149 if (width < 0) {
150 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
151 width, font->lfWidth );
152 width = -width;
154 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
155 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
156 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
157 if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
158 else switch(font->lfPitchAndFamily & 0xf0)
160 case FF_ROMAN:
161 family = FONT_TranslateName( "roman" );
162 break;
163 case FF_SWISS:
164 family = FONT_TranslateName( "swiss" );
165 break;
166 case FF_MODERN:
167 family = FONT_TranslateName( "modern" );
168 break;
169 case FF_SCRIPT:
170 family = FONT_TranslateName( "script" );
171 break;
172 case FF_DECORATIVE:
173 family = FONT_TranslateName( "decorative" );
174 break;
175 default:
176 family = "*-*";
177 break;
180 oldheight = height;
181 oldspacing = spacing;
182 while (TRUE) {
183 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
184 if ( width == 0 )
185 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
186 family, weight, slant, height, spacing, charset);
187 else
188 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
189 family, weight, slant, height, spacing, width, charset);
190 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
191 names = XListFonts( display, pattern, 1, &count );
192 if (count > 0) break;
193 if (spacing == 'm') /* try 'c' if no 'm' found */ {
194 spacing = 'c';
195 continue;
196 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
197 spacing = '*';
198 continue;
200 spacing = oldspacing;
201 height -= 10;
202 if (height < 10) {
203 if (slant == 'i') {
204 /* try oblique if no italic font */
205 slant = 'o';
206 height = oldheight;
207 continue;
209 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
210 /* If a fixed spacing font could not be found, ignore
211 * the family */
212 family = "*-*";
213 height = oldheight;
214 continue;
216 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
217 return NULL;
220 dprintf_font(stddeb," Found '%s'\n", *names );
221 fontStruct = XLoadQueryFont( display, *names );
222 XFreeFontNames( names );
223 return fontStruct;
227 /***********************************************************************
228 * FONT_GetMetrics
230 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
231 TEXTMETRIC * metrics )
233 int average, i, count;
234 unsigned long prop;
236 metrics->tmAscent = xfont->ascent;
237 metrics->tmDescent = xfont->descent;
238 metrics->tmHeight = xfont->ascent + xfont->descent;
240 metrics->tmInternalLeading = 0;
241 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
242 metrics->tmInternalLeading = xfont->ascent - (short)prop;
243 metrics->tmExternalLeading = 0;
244 metrics->tmMaxCharWidth = xfont->max_bounds.width;
245 metrics->tmWeight = logfont->lfWeight;
246 metrics->tmItalic = logfont->lfItalic;
247 metrics->tmUnderlined = logfont->lfUnderline;
248 metrics->tmStruckOut = logfont->lfStrikeOut;
249 metrics->tmFirstChar = xfont->min_char_or_byte2;
250 metrics->tmLastChar = xfont->max_char_or_byte2;
251 metrics->tmDefaultChar = xfont->default_char;
252 metrics->tmBreakChar = ' ';
253 metrics->tmCharSet = logfont->lfCharSet;
254 metrics->tmOverhang = 0;
255 metrics->tmDigitizedAspectX = 1;
256 metrics->tmDigitizedAspectY = 1;
257 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
258 if (logfont->lfPitchAndFamily & FIXED_PITCH)
259 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
261 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
262 else
264 XCharStruct * charPtr = xfont->per_char;
265 average = count = 0;
266 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
268 if (!CI_NONEXISTCHAR( charPtr ))
270 average += charPtr->width;
271 count++;
273 charPtr++;
275 if (count) average = (average + count/2) / count;
277 metrics->tmAveCharWidth = average;
280 /***********************************************************************
281 * GetGlyphOutLine (GDI.309)
283 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
284 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
286 fprintf( stdnimp,"GetGlyphOutLine("NPFMT", '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
287 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
288 return (DWORD)-1; /* failure */
292 /***********************************************************************
293 * CreateScalableFontResource (GDI.310)
295 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
296 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
298 /* fHidden=1 - only visible for the calling app, read-only, not
299 * enumbered with EnumFonts/EnumFontFamilies
300 * lpszCurrentPath can be NULL
302 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
303 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
304 return FALSE; /* create failed */
308 /***********************************************************************
309 * CreateFontIndirect (GDI.57)
311 HFONT CreateFontIndirect( const LOGFONT * font )
313 FONTOBJ * fontPtr;
314 HFONT hfont;
316 if (!font)
318 fprintf(stderr, "CreateFontIndirect : font is NULL : returning NULL\n");
319 return 0;
321 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
322 if (!hfont) return 0;
323 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
324 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
325 AnsiLower( fontPtr->logfont.lfFaceName );
326 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return "NPFMT"\n",
327 font, font->lfHeight, font->lfWidth, hfont);
328 return hfont;
332 /***********************************************************************
333 * CreateFont (GDI.56)
335 HFONT CreateFont( INT height, INT width, INT esc, INT orient, INT weight,
336 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
337 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
338 LPCSTR name )
340 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
341 strikeout, charset, outpres, clippres, quality, pitch, };
342 dprintf_font(stddeb,"CreateFont(%d,%d)\n", height, width);
343 if (name)
345 strncpy( logfont.lfFaceName, name, LF_FACESIZE - 1 );
346 logfont.lfFaceName[LF_FACESIZE - 1] = '\0';
348 else logfont.lfFaceName[0] = '\0';
349 return CreateFontIndirect( &logfont );
353 /***********************************************************************
354 * FONT_GetObject
356 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
358 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
359 memcpy( buffer, &font->logfont, count );
360 return count;
364 /***********************************************************************
365 * FONT_SelectObject
367 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
369 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
370 X_PHYSFONT * stockPtr;
371 HFONT prevHandle = dc->w.hFont;
372 XFontStruct * fontStruct;
373 dprintf_font(stddeb,"FONT_SelectObject(%p, "NPFMT", %p)\n",
374 dc, hfont, font);
376 #if 0 /* From the code in SelectObject, this can not happen */
377 /* Load font if necessary */
378 if (!font)
380 HFONT hnewfont;
382 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
383 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
384 DEFAULT_QUALITY, FF_DONTCARE, "*" );
385 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
387 #endif
389 if (dc->header.wMagic == METAFILE_DC_MAGIC)
390 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
391 return prevHandle;
392 else
393 return 0;
395 /* Must be DWORD for WINELIB32 support */
396 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
397 stockPtr = &stockFonts[(DWORD)hfont - (DWORD)FIRST_STOCK_FONT];
398 else
399 stockPtr = NULL;
401 if (!stockPtr || !stockPtr->fstruct)
403 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
405 /* If it is not a stock font, we can simply return 0 */
406 if (!stockPtr) return 0;
407 /* Otherwise we must try to find a substitute */
408 dprintf_font(stddeb,"Loading font 'fixed' for "NPFMT"\n", hfont );
409 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
410 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
411 fontStruct = XLoadQueryFont( display, "fixed" );
412 if (!fontStruct)
414 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
415 exit( 1 );
419 else
421 fontStruct = stockPtr->fstruct;
422 dprintf_font(stddeb,
423 "FONT_SelectObject: Loaded font from cache "NPFMT" %p\n",
424 hfont, fontStruct );
427 /* Free previous font */
429 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
431 if (dc->u.x.font.fstruct)
432 XFreeFont( display, dc->u.x.font.fstruct );
435 /* Store font */
437 dc->w.hFont = hfont;
438 if (stockPtr)
440 if (!stockPtr->fstruct)
442 stockPtr->fstruct = fontStruct;
443 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
445 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
447 else
449 dc->u.x.font.fstruct = fontStruct;
450 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
452 return prevHandle;
456 /***********************************************************************
457 * GetTextCharacterExtra (GDI.89)
459 short GetTextCharacterExtra( HDC hdc )
461 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
462 if (!dc) return 0;
463 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
464 / dc->w.VportExtX );
468 /***********************************************************************
469 * SetTextCharacterExtra (GDI.8)
471 short SetTextCharacterExtra( HDC hdc, short extra )
473 short prev;
474 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
475 if (!dc) return 0;
476 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
477 prev = dc->w.charExtra;
478 dc->w.charExtra = abs(extra);
479 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
483 /***********************************************************************
484 * SetTextJustification (GDI.10)
486 short SetTextJustification( HDC hdc, short extra, short breaks )
488 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
489 if (!dc) return 0;
491 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
492 if (!extra) breaks = 0;
493 dc->w.breakTotalExtra = extra;
494 dc->w.breakCount = breaks;
495 if (breaks)
497 dc->w.breakExtra = extra / breaks;
498 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
500 else
502 dc->w.breakExtra = 0;
503 dc->w.breakRem = 0;
505 return 1;
509 /***********************************************************************
510 * GetTextFace (GDI.92)
512 INT GetTextFace( HDC hdc, INT count, LPSTR name )
514 FONTOBJ *font;
516 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
517 if (!dc) return 0;
518 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
519 return 0;
520 lstrcpyn( name, font->logfont.lfFaceName, count );
521 return strlen(name);
525 /***********************************************************************
526 * GetTextExtent (GDI.91)
528 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
530 SIZE size;
531 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
532 return MAKELONG( size.cx, size.cy );
536 /***********************************************************************
537 * GetTextExtentPoint (GDI.471)
539 BOOL GetTextExtentPoint( HDC hdc, LPCSTR str, short count, LPSIZE size )
541 int dir, ascent, descent;
542 XCharStruct info;
544 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
545 if (!dc) return FALSE;
546 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
547 &ascent, &descent, &info );
548 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
549 * dc->w.WndExtX / dc->w.VportExtX);
550 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
551 * dc->w.WndExtY / dc->w.VportExtY);
553 dprintf_font(stddeb,"GetTextExtentPoint("NPFMT" '%*.*s' %d %p): returning %ld,%ld\n",
554 hdc, count, count, str, count, size, (LONG)size->cx,
555 (LONG)size->cy );
556 return TRUE;
560 /***********************************************************************
561 * GetTextMetrics (GDI.93)
563 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
565 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
566 if (!dc) return FALSE;
567 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
569 metrics->tmAscent = abs( metrics->tmAscent
570 * dc->w.WndExtY / dc->w.VportExtY );
571 metrics->tmDescent = abs( metrics->tmDescent
572 * dc->w.WndExtY / dc->w.VportExtY );
573 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
574 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
575 * dc->w.WndExtY / dc->w.VportExtY );
576 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
577 * dc->w.WndExtY / dc->w.VportExtY );
578 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
579 * dc->w.WndExtX / dc->w.VportExtX );
580 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
581 * dc->w.WndExtX / dc->w.VportExtX );
582 return TRUE;
586 /***********************************************************************
587 * SetMapperFlags (GDI.349)
589 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
591 dprintf_font(stdnimp,"SetmapperFlags("NPFMT", %08lX) // Empty Stub !\n",
592 hDC, dwFlag);
593 return 0L;
597 /***********************************************************************
598 * GetCharABCWidths (GDI.307)
600 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC lpABC)
602 /* No TrueType fonts in Wine */
603 return FALSE;
607 /***********************************************************************
608 * GetCharWidth (GDI.350)
610 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
612 int i, j;
613 XFontStruct *xfont;
614 XCharStruct *cs, *def;
616 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
617 if (!dc) return FALSE;
618 xfont = dc->u.x.font.fstruct;
620 /* fixed font? */
621 if (xfont->per_char == NULL)
623 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
624 *(lpBuffer + j) = xfont->max_bounds.width;
625 return TRUE;
628 CI_GET_DEFAULT_INFO(xfont, def);
630 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
632 CI_GET_CHAR_INFO(xfont, i, def, cs);
633 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
634 if (*(lpBuffer + j) < 0)
635 *(lpBuffer + j) = 0;
637 return TRUE;
641 /***********************************************************************
642 * AddFontResource (GDI.119)
644 INT AddFontResource( LPCSTR str )
646 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
647 return 1;
651 /***********************************************************************
652 * RemoveFontResource (GDI.136)
654 BOOL RemoveFontResource( LPSTR str )
656 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
657 return TRUE;
661 /*************************************************************************
662 * ParseFontParms [internal]
664 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
666 int i;
667 #if 0
668 dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n",
669 lpFont, wParmsNo, lpRetStr, wMaxSiz);
670 #endif
671 if (lpFont == NULL) return 0;
672 if (lpRetStr == NULL) return 0;
673 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
674 if (*lpFont == '-') i++;
675 lpFont++;
677 if (i == wParmsNo) {
678 if (*lpFont == '-') lpFont++;
679 wMaxSiz--;
680 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
681 *(lpRetStr + i) = *lpFont++;
682 *(lpRetStr + i) = '\0';
683 #if 0
684 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
685 #endif
686 return i;
688 else
689 lpRetStr[0] = '\0';
690 return 0;
694 /*************************************************************************
695 * InitFontsList [internal]
698 static int logfcmp(const void *a,const void *b)
700 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
703 void InitFontsList(void)
705 char str[32];
706 char pattern[100];
707 char *family, *weight, *charset;
708 char **names;
709 char slant, spacing;
710 int i, count;
711 LPLOGFONT lpNewFont;
712 weight = "medium";
713 slant = 'r';
714 spacing = '*';
715 charset = "*";
716 family = "*-*";
717 dprintf_font(stddeb,"InitFontsList !\n");
718 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
719 family, weight, slant, spacing, charset);
720 names = XListFonts( display, pattern, MAX_FONTS, &count );
721 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
722 for (i = 0; i < count; i++) {
723 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
724 if (lpNewFont == NULL) {
725 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
726 break;
728 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
729 ParseFontParms(names[i], 2, str, sizeof(str));
730 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
731 AnsiUpper(str);
732 strcpy(lpNewFont->lfFaceName, str);
733 ParseFontParms(names[i], 8, str, sizeof(str));
734 lpNewFont->lfHeight = atoi(str) / 10;
735 ParseFontParms(names[i], 12, str, sizeof(str));
736 lpNewFont->lfWidth = atoi(str) / 10;
737 lpNewFont->lfEscapement = 0;
738 lpNewFont->lfOrientation = 0;
739 lpNewFont->lfWeight = FW_REGULAR;
740 lpNewFont->lfItalic = 0;
741 lpNewFont->lfUnderline = 0;
742 lpNewFont->lfStrikeOut = 0;
743 ParseFontParms(names[i], 13, str, sizeof(str));
744 if (strcmp(str, "iso8859") == 0) {
745 lpNewFont->lfCharSet = ANSI_CHARSET;
746 } else {
747 lpNewFont->lfCharSet = OEM_CHARSET;
749 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
750 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
751 lpNewFont->lfQuality = DEFAULT_QUALITY;
752 ParseFontParms(names[i], 11, str, sizeof(str));
753 switch(str[0]) {
754 case 'p':
755 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
756 break;
757 case 'm':
758 case 'c':
759 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
760 break;
761 default:
762 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
763 break;
765 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
766 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
767 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
768 lpLogFontList[i] = lpNewFont;
769 lpLogFontList[i+1] = NULL;
771 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
772 XFreeFontNames(names);
776 /*************************************************************************
777 * EnumFonts [GDI.70]
779 INT EnumFonts(HDC hDC, LPCTSTR lpFaceName, FONTENUMPROC lpEnumFunc, LPARAM lpData)
781 HANDLE hLog;
782 HANDLE hMet;
783 HFONT hFont;
784 HFONT hOldFont;
785 LPLOGFONT lpLogFont;
786 LPTEXTMETRIC lptm;
787 LPSTR lpOldName;
788 char FaceName[LF_FACESIZE];
789 int nRet = 0;
790 int i;
792 dprintf_font(stddeb,"EnumFonts("NPFMT", %p='%s', %08lx, %08lx)\n",
793 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
794 if (lpEnumFunc == 0) return 0;
795 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
796 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
797 if (lpLogFont == NULL) {
798 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
799 return 0;
801 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
802 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
803 if (lptm == NULL) {
804 GDI_HEAP_FREE(hLog);
805 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
806 return 0;
808 if (lpFaceName != NULL) {
809 strcpy(FaceName, lpFaceName);
810 AnsiUpper(FaceName);
812 lpOldName = NULL;
814 if (lpLogFontList[0] == NULL) InitFontsList();
815 for(i = 0; lpLogFontList[i] != NULL; i++) {
816 if (lpFaceName == NULL) {
817 if (lpOldName != NULL) {
818 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
820 lpOldName = lpLogFontList[i]->lfFaceName;
821 } else {
822 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
824 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
825 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
826 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
827 hFont = CreateFontIndirect(lpLogFont);
828 hOldFont = SelectObject(hDC, hFont);
829 GetTextMetrics(hDC, lptm);
830 SelectObject(hDC, hOldFont);
831 DeleteObject(hFont);
832 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
833 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
834 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
835 if (nRet == 0) {
836 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
837 break;
840 GDI_HEAP_FREE(hMet);
841 GDI_HEAP_FREE(hLog);
842 return nRet;
846 /*************************************************************************
847 * EnumFontFamilies [GDI.330]
849 INT EnumFontFamilies(HDC hDC, LPCTSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
851 HANDLE hLog;
852 HANDLE hMet;
853 HFONT hFont;
854 HFONT hOldFont;
855 LPENUMLOGFONT lpEnumLogFont;
856 LPTEXTMETRIC lptm;
857 LPSTR lpOldName;
858 char FaceName[LF_FACESIZE];
859 int nRet = 0;
860 int i;
862 dprintf_font(stddeb,"EnumFontFamilies("NPFMT", %p, %08lx, %08lx)\n",
863 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
864 if (lpEnumFunc == 0) return 0;
865 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
866 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
867 if (lpEnumLogFont == NULL) {
868 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
869 return 0;
871 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
872 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
873 if (lptm == NULL) {
874 GDI_HEAP_FREE(hLog);
875 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
876 return 0;
878 lpOldName = NULL;
879 if (lpszFamily != NULL) {
880 strcpy(FaceName, lpszFamily);
881 AnsiUpper(FaceName);
883 if (lpLogFontList[0] == NULL) InitFontsList();
884 for(i = 0; lpLogFontList[i] != NULL; i++) {
885 if (lpszFamily == NULL) {
886 if (lpOldName != NULL) {
887 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
889 lpOldName = lpLogFontList[i]->lfFaceName;
890 } else {
891 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
893 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
894 strcpy(lpEnumLogFont->elfFullName,"");
895 strcpy(lpEnumLogFont->elfStyle,"");
896 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
897 hOldFont = SelectObject(hDC, hFont);
898 GetTextMetrics(hDC, lptm);
899 SelectObject(hDC, hOldFont);
900 DeleteObject(hFont);
901 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
903 nRet = CallEnumFontFamProc( lpEnumFunc,
904 GDI_HEAP_SEG_ADDR(hLog),
905 GDI_HEAP_SEG_ADDR(hMet),
906 0, lpData );
907 if (nRet == 0) {
908 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
909 break;
912 GDI_HEAP_FREE(hMet);
913 GDI_HEAP_FREE(hLog);
914 return nRet;
917 /*************************************************************************
918 * GetRasterizerCaps [GDI.313]
921 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
923 /* This is not much more than a dummy */
924 RASTERIZER_STATUS rs;
926 rs.nSize = sizeof(rs);
927 rs.wFlags = 0;
928 rs.nLanguageID = 0;
929 return True;
932 /*************************************************************************
933 * GetKerningPairs [GDI.332]
935 int GetKerningPairs(HDC hDC,int cBufLen,LPKERNINGPAIR lpKerningPairs)
937 /* Wine fonts are ugly and don't support kerning :) */
938 return 0;