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