]> git.saurik.com Git - wxWidgets.git/blame - src/os2/fontutil.cpp
Deallocate wxThreadSpecificInfo when wxThread ends.
[wxWidgets.git] / src / os2 / fontutil.cpp
CommitLineData
d8cde57b 1///////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/msw/fontutil.cpp
d8cde57b
DW
3// Purpose: font-related helper functions for wxMSW
4// Author: Modified by David Webster for OS/2
5// Modified by:
6// Created: 01.03.00
d8cde57b 7// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 8// Licence: wxWindows licence
d8cde57b
DW
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
6670f564
WS
22#define DEBUG_PRINTF(NAME) \
23 { \
24 static int raz=0; \
25 printf( #NAME " %i\n",raz); fflush(stdout); \
26 raz++; \
27 }
28
d8cde57b 29#ifndef WX_PRECOMP
3417f661 30 #include "wx/app.h"
d8cde57b
DW
31 #include "wx/string.h"
32 #include "wx/log.h"
33 #include "wx/intl.h"
34#endif //WX_PRECOMP
35
36#include "wx/os2/private.h"
37
38#include "wx/fontutil.h"
39#include "wx/fontmap.h"
bd6685b3 40#include "wx/encinfo.h"
d8cde57b
DW
41
42#include "wx/tokenzr.h"
43
44// ============================================================================
45// implementation
46// ============================================================================
47
48// ----------------------------------------------------------------------------
49// wxNativeEncodingInfo
50// ----------------------------------------------------------------------------
51
52// convert to/from the string representation: format is
1e1d0be1 53// encodingid;facename[;charset]
d8cde57b 54
6670f564 55bool wxNativeEncodingInfo::FromString( const wxString& rsStr )
d8cde57b 56{
9a83f860 57 wxStringTokenizer vTokenizer(rsStr, wxT(";"));
e99762c0
DW
58 wxString sEncid = vTokenizer.GetNextToken();
59 long lEnc;
d8cde57b 60
e99762c0 61 if (!sEncid.ToLong(&lEnc))
1e1d0be1 62 return FALSE;
e99762c0
DW
63 encoding = (wxFontEncoding)lEnc;
64 facename = vTokenizer.GetNextToken();
65 if (!facename)
d8cde57b
DW
66 return FALSE;
67
e99762c0
DW
68 wxString sTmp = vTokenizer.GetNextToken();
69
70 if (!sTmp)
d8cde57b 71 {
e99762c0 72 charset = 850;
d8cde57b
DW
73 }
74 else
75 {
9a83f860 76 if ( wxSscanf(sTmp, wxT("%u"), &charset) != 1 )
d8cde57b
DW
77 {
78 // should be a number!
79 return FALSE;
80 }
81 }
6670f564 82 return true;
e99762c0 83} // end of wxNativeEncodingInfo::FromString
d8cde57b
DW
84
85wxString wxNativeEncodingInfo::ToString() const
86{
e99762c0 87 wxString sStr;
7e99520b 88
9a83f860 89 sStr << (long)encoding << wxT(';') << facename;
1e1d0be1 90
e99762c0 91 if (charset != 850)
d8cde57b 92 {
9a83f860 93 sStr << wxT(';') << charset;
d8cde57b 94 }
e99762c0
DW
95 return sStr;
96} // end of wxNativeEncodingInfo::ToString
d8cde57b
DW
97
98// ----------------------------------------------------------------------------
99// helper functions
100// ----------------------------------------------------------------------------
101
6670f564
WS
102bool wxGetNativeFontEncoding( wxFontEncoding vEncoding,
103 wxNativeEncodingInfo* pInfo )
d8cde57b 104{
9a83f860 105 wxCHECK_MSG(pInfo, FALSE, wxT("bad pointer in wxGetNativeFontEncoding") );
e99762c0 106 if (vEncoding == wxFONTENCODING_DEFAULT)
d8cde57b 107 {
e99762c0 108 vEncoding = wxFont::GetDefaultEncoding();
d8cde57b 109 }
e99762c0 110 switch (vEncoding)
d8cde57b 111 {
d8cde57b
DW
112 case wxFONTENCODING_ISO8859_1:
113 case wxFONTENCODING_ISO8859_15:
e99762c0
DW
114 case wxFONTENCODING_CP1250:
115 pInfo->charset = 1250;
d8cde57b
DW
116 break;
117
e99762c0
DW
118 case wxFONTENCODING_ISO8859_2:
119 case wxFONTENCODING_CP1252:
120 pInfo->charset = 1252;
d8cde57b
DW
121 break;
122
e99762c0
DW
123 case wxFONTENCODING_ISO8859_4:
124 case wxFONTENCODING_ISO8859_10:
125 pInfo->charset = 921; // what is baltic?
d8cde57b
DW
126 break;
127
e99762c0
DW
128 case wxFONTENCODING_ISO8859_5:
129 case wxFONTENCODING_CP1251:
130 pInfo->charset = 1251;
d8cde57b
DW
131 break;
132
e99762c0
DW
133 case wxFONTENCODING_ISO8859_6:
134 pInfo->charset = 864;
d8cde57b
DW
135 break;
136
e99762c0
DW
137 case wxFONTENCODING_ISO8859_7:
138 pInfo->charset = 869;
d8cde57b
DW
139 break;
140
e99762c0
DW
141 case wxFONTENCODING_ISO8859_8:
142 pInfo->charset = 862;
d8cde57b
DW
143 break;
144
e99762c0
DW
145 case wxFONTENCODING_ISO8859_9:
146 pInfo->charset = 857;
d8cde57b
DW
147 break;
148
e99762c0
DW
149 case wxFONTENCODING_ISO8859_11:
150 pInfo->charset = 874; // what is thai
d8cde57b
DW
151 break;
152
153 case wxFONTENCODING_CP437:
e99762c0 154 pInfo->charset = 437;
d8cde57b 155 break;
e99762c0 156
d8cde57b 157 default:
e99762c0
DW
158 wxFAIL_MSG(wxT("unsupported encoding"));
159 // fall through
d8cde57b 160
e99762c0
DW
161 case wxFONTENCODING_SYSTEM:
162 pInfo->charset = 850;
163 break;
164 }
6670f564 165 return true;
e99762c0 166} // end of wxGetNativeFontEncoding
d8cde57b 167
cc95f4f9
DW
168wxFontEncoding wxGetFontEncFromCharSet(
169 int nCharSet
170)
171{
172 wxFontEncoding eFontEncoding;
173
174 switch (nCharSet)
175 {
176 default:
177 case 1250:
178 eFontEncoding = wxFONTENCODING_CP1250;
179 break;
180
181 case 1252:
182 eFontEncoding = wxFONTENCODING_CP1252;
183 break;
184
185 case 921:
186 eFontEncoding = wxFONTENCODING_ISO8859_4;
187 break;
188
189 case 1251:
190 eFontEncoding = wxFONTENCODING_CP1251;
191 break;
192
193 case 864:
194 eFontEncoding = wxFONTENCODING_ISO8859_6;
195 break;
196
197 case 869:
198 eFontEncoding = wxFONTENCODING_ISO8859_7;
199 break;
200
201 case 862:
202 eFontEncoding = wxFONTENCODING_ISO8859_8;
203 break;
204
205 case 857:
206 eFontEncoding = wxFONTENCODING_ISO8859_9;
207 break;
208
209 case 874:
210 eFontEncoding = wxFONTENCODING_ISO8859_11;
211 break;
212
213 case 437:
214 eFontEncoding = wxFONTENCODING_CP437;
215 break;
216 }
217 return eFontEncoding;
218} // end of wxGetNativeFontEncoding
219
6670f564 220bool wxTestFontEncoding( const wxNativeEncodingInfo& rInfo )
d8cde57b 221{
6670f564
WS
222 FATTRS vLogFont;
223 HPS hPS;
e99762c0
DW
224
225 hPS = ::WinGetPS(HWND_DESKTOP);
226
227 memset(&vLogFont, '\0', sizeof(FATTRS)); // all default values
228 vLogFont.usRecordLength = sizeof(FATTRS);
6670f564 229 vLogFont.usCodePage = (USHORT)rInfo.charset;
e99762c0
DW
230 vLogFont.lMaxBaselineExt = 0L; // Outline fonts should use 0
231 vLogFont.lAveCharWidth = 0L; // Outline fonts should use 0
232 vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
233 FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
234
e408bf52 235 wxStrlcpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename));
e99762c0
DW
236
237 if (!::GpiCreateLogFont( hPS
238 ,NULL
239 ,1L
240 ,&vLogFont
241 ))
d8cde57b 242 {
e99762c0 243 ::WinReleasePS(hPS);
d8cde57b
DW
244 return FALSE;
245 }
e99762c0 246 ::WinReleasePS(hPS);
6670f564 247 return true;
e99762c0 248} // end of wxTestFontEncoding
d8cde57b
DW
249
250// ----------------------------------------------------------------------------
251// wxFont <-> LOGFONT conversion
252// ----------------------------------------------------------------------------
253
a4353f07
DW
254void wxConvertVectorFontSize(
255 FIXED fxPointSize
256, PFATTRS pFattrs
257)
258{
259 HPS hPS;
260 HDC hDC;
261 LONG lXFontResolution;
262 LONG lYFontResolution;
263 SIZEF vSizef;
264
265 hPS = WinGetScreenPS(HWND_DESKTOP); // Screen presentation space
266
267 //
268 // Query device context for the screen and then query
269 // the resolution of the device for the device context.
270 //
271
272 hDC = GpiQueryDevice(hPS);
273 DevQueryCaps( hDC, CAPS_HORIZONTAL_FONT_RES, (LONG)1, &lXFontResolution);
274 DevQueryCaps( hDC, CAPS_VERTICAL_FONT_RES, (LONG)1, &lYFontResolution);
275
276 //
277 // Calculate the size of the character box, based on the
278 // point size selected and the resolution of the device.
279 // The size parameters are of type FIXED, NOT int.
280 // NOTE: 1 point == 1/72 of an inch.
281 //
282
ad8dd67e
SN
283 // multiply first to avoid getting vSizef.cx,cy = 0 since fxPointSize
284 // is normally < 72 and FontResolution is typically ca. 100
285 vSizef.cx = (FIXED)( (fxPointSize * lXFontResolution) / 72 );
286 vSizef.cy = (FIXED)( (fxPointSize * lYFontResolution) / 72 );
a4353f07 287
ad8dd67e
SN
288 if (pFattrs)
289 {
290 pFattrs->lMaxBaselineExt = MAKELONG( HIUSHORT( vSizef.cy ), 0 );
291 pFattrs->lAveCharWidth = MAKELONG( HIUSHORT( vSizef.cx ), 0 );
292 }
a4353f07
DW
293 WinReleasePS(hPS);
294
295} // end of wxConvertVectorPointSize
296
6670f564
WS
297void wxFillLogFont( LOGFONT* pFattrs, // OS2 GPI FATTRS
298 PFACENAMEDESC pFaceName,
299 HPS* phPS,
300 bool* pbInternalPS,
301 long* pflId,
302 wxString& sFaceName,
303 wxFont* pFont )
d8cde57b 304{
6670f564
WS
305 LONG lNumFonts = 0L; // For system font count
306 ERRORID vError; // For logging API errors
307 LONG lTemp = 0L;
308 bool bInternalPS = false; // if we have to create one
309 PFONTMETRICS pFM = NULL;
cc95f4f9
DW
310
311 //
312 // Initial house cleaning to free data buffers and ensure we have a
313 // functional PS to work with
314 //
54ffa107 315 if (!*phPS)
cc95f4f9 316 {
54ffa107 317 *phPS = ::WinGetPS(HWND_DESKTOP);
6670f564 318 bInternalPS = true;
cc95f4f9
DW
319 }
320
321 //
322 // Determine the number of fonts.
323 //
54ffa107 324 if((lNumFonts = ::GpiQueryFonts( *phPS
a23692f0 325 ,QF_PUBLIC | QF_PRIVATE
54ffa107
DW
326 ,NULL
327 ,&lTemp
328 ,(LONG) sizeof(FONTMETRICS)
329 ,NULL
330 )) < 0L)
331 {
332 ERRORID vError;
333 wxString sError;
334
335 vError = ::WinGetLastError(wxGetInstance());
336 sError = wxPMErrorToStr(vError);
337 return;
338 }
cc95f4f9
DW
339
340 //
341 // Allocate space for the font metrics.
342 //
343 pFM = new FONTMETRICS[lNumFonts + 1];
e99762c0 344
cc95f4f9
DW
345 //
346 // Retrieve the font metrics.
347 //
348 lTemp = lNumFonts;
54ffa107 349 lTemp = ::GpiQueryFonts( *phPS
cc95f4f9
DW
350 ,QF_PUBLIC
351 ,NULL
352 ,&lTemp
353 ,(LONG) sizeof(FONTMETRICS)
354 ,pFM
355 );
356 pFont->SetFM( pFM
357 ,(int)lNumFonts
358 );
359
cc95f4f9
DW
360 //
361 // Initialize FATTR and FACENAMEDESC
362 //
363 pFattrs->usRecordLength = sizeof(FATTRS);
a4353f07 364 pFattrs->fsFontUse = FATTR_FONTUSE_OUTLINE; // only outline fonts allowed
cc95f4f9
DW
365 pFattrs->fsType = 0;
366 pFattrs->lMaxBaselineExt = pFattrs->lAveCharWidth = 0;
367 pFattrs->idRegistry = 0;
368 pFattrs->lMatch = 0;
369
370 pFaceName->usSize = sizeof(FACENAMEDESC);
a23692f0
DW
371 pFaceName->usWeightClass = FWEIGHT_DONT_CARE;
372 pFaceName->usWidthClass = FWIDTH_DONT_CARE;
cc95f4f9 373 pFaceName->usReserved = 0;
e99762c0 374 pFaceName->flOptions = 0;
cc95f4f9
DW
375
376 //
377 // This does the actual selection of fonts
378 //
379 wxOS2SelectMatchingFontByName( pFattrs
380 ,pFaceName
381 ,pFM
382 ,(int)lNumFonts
383 ,pFont
384 );
385 //
386 // We should now have the correct FATTRS set with the selected
387 // font, so now we need to generate an ID
388 //
54ffa107 389 long lNumLids = ::GpiQueryNumberSetIds(*phPS);
cc95f4f9
DW
390
391 if(lNumLids )
392 {
393 long alTypes[255];
394 STR8 azNames[255];
395 long alIds[255];
396
d697657f 397 memset(alIds, 0, sizeof(long) * 255);
54ffa107 398 if(!::GpiQuerySetIds( *phPS
cc95f4f9
DW
399 ,lNumLids
400 ,alTypes
401 ,azNames
402 ,alIds
403 ))
404 {
405 if (bInternalPS)
54ffa107 406 ::WinReleasePS(*phPS);
cc95f4f9
DW
407 return;
408 }
d697657f
DW
409 if (*pflId == 0L)
410 *pflId = 1L;
0d598bae 411 for(unsigned long LCNum = 0; LCNum < (unsigned long)lNumLids; LCNum++)
cc95f4f9
DW
412 if(alIds[LCNum] == *pflId)
413 ++*pflId;
414 if(*pflId > 254) // wow, no id available!
415 {
416 if (bInternalPS)
54ffa107 417 ::WinReleasePS(*phPS);
cc95f4f9
DW
418 return;
419 }
420 }
54ffa107
DW
421 else
422 *pflId = 1L;
cc95f4f9
DW
423 //
424 // Release and delete the current font
425 //
54ffa107
DW
426 ::GpiSetCharSet(*phPS, LCID_DEFAULT);/* release the font before deleting */
427 ::GpiDeleteSetId(*phPS, 1L); /* delete the logical font */
cc95f4f9
DW
428
429 //
430 // Now build a facestring
431 //
432 char zFacename[128];
433
434 strcpy(zFacename, pFattrs->szFacename);
435
54ffa107 436 if(::GpiQueryFaceString( *phPS
cc95f4f9
DW
437 ,zFacename
438 ,pFaceName
439 ,FACESIZE
440 ,pFattrs->szFacename
441 ) == GPI_ERROR)
442 {
443 vError = ::WinGetLastError(vHabmain);
444 }
0fba44b4 445 sFaceName = (wxChar*)zFacename;
828621c2 446 *pbInternalPS = bInternalPS;
cc95f4f9
DW
447
448 //
449 // That's it, we now have everything we need to actually create the font
450 //
451} // end of wxFillLogFont
452
453void wxOS2SelectMatchingFontByName(
454 PFATTRS pFattrs
455, PFACENAMEDESC pFaceName
456, PFONTMETRICS pFM
457, int nNumFonts
458, const wxFont* pFont
459)
460{
461 int i;
cc95f4f9 462 int nPointSize;
cc95f4f9 463 int nIs;
cc95f4f9 464 int nMinDiff0;
cc95f4f9
DW
465 int anDiff[16];
466 int anMinDiff[16];
e1146627 467 int nIndex = 0;
0fba44b4 468 wxChar zFontFaceName[FACESIZE];
cc95f4f9
DW
469 wxString sFaceName;
470 USHORT usWeightClass;
471 int fsSelection = 0;
472
473 nMinDiff0 = 0xf000;
474 for(i = 0;i < 16; i++)
475 anMinDiff[i] = nMinDiff0;
476
e99762c0 477 switch (pFont->GetFamily())
d8cde57b
DW
478 {
479 case wxSCRIPT:
1b75810c 480 sFaceName = wxT("Tms Rmn");
d8cde57b
DW
481 break;
482
483 case wxDECORATIVE:
07df68c8
DW
484 sFaceName = wxT("WarpSans");
485 break;
486
d8cde57b 487 case wxROMAN:
1b75810c 488 sFaceName = wxT("Tms Rmn");
d8cde57b
DW
489 break;
490
491 case wxTELETYPE:
1b75810c 492 sFaceName = wxT("Courier") ;
d8cde57b
DW
493 break;
494
e3bfcacf 495 case wxMODERN:
1b75810c 496 sFaceName = wxT("System VIO") ;
e3bfcacf
DW
497 break;
498
d8cde57b 499 case wxSWISS:
e3bfcacf 500 sFaceName = wxT("Helv") ;
d8cde57b
DW
501 break;
502
503 case wxDEFAULT:
504 default:
a23692f0 505 sFaceName = wxT("System VIO") ;
d8cde57b
DW
506 }
507
e99762c0 508 switch (pFont->GetWeight())
d8cde57b
DW
509 {
510 default:
9a83f860 511 wxFAIL_MSG(wxT("unknown font weight"));
cc95f4f9
DW
512 // fall through
513 usWeightClass = FWEIGHT_DONT_CARE;
e99762c0 514 break;
d8cde57b
DW
515
516 case wxNORMAL:
cc95f4f9 517 usWeightClass = FWEIGHT_NORMAL;
d8cde57b
DW
518 break;
519
520 case wxLIGHT:
cc95f4f9 521 usWeightClass = FWEIGHT_LIGHT;
d8cde57b
DW
522 break;
523
524 case wxBOLD:
cc95f4f9 525 usWeightClass = FWEIGHT_BOLD;
e99762c0
DW
526 break;
527
cc95f4f9
DW
528 case wxFONTWEIGHT_MAX:
529 usWeightClass = FWEIGHT_ULTRA_BOLD;
d8cde57b
DW
530 break;
531 }
cc95f4f9 532 pFaceName->usWeightClass = usWeightClass;
d8cde57b 533
e99762c0
DW
534 switch (pFont->GetStyle())
535 {
536 case wxITALIC:
537 case wxSLANT:
cc95f4f9
DW
538 fsSelection = FM_SEL_ITALIC;
539 pFaceName->flOptions = FTYPE_ITALIC;
e99762c0
DW
540 break;
541
542 default:
543 wxFAIL_MSG(wxT("unknown font slant"));
544 // fall through
d8cde57b 545
e99762c0 546 case wxNORMAL:
cc95f4f9 547 fsSelection = 0;
e99762c0
DW
548 break;
549 }
cc95f4f9 550
e408bf52 551 wxStrlcpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
cc95f4f9 552 nPointSize = pFont->GetPointSize();
e99762c0
DW
553
554 //
cc95f4f9 555 // Matching logic to find the right FM struct
e99762c0 556 //
cc95f4f9
DW
557 nIndex = 0;
558 for(i = 0, nIs = 0; i < nNumFonts; i++)
d8cde57b 559 {
0fba44b4 560 anDiff[0] = wxGpiStrcmp((wxChar*)pFM[i].szFacename, zFontFaceName);
cc95f4f9
DW
561 anDiff[1] = abs(pFM[i].lEmHeight - nPointSize);
562 anDiff[2] = abs(pFM[i].usWeightClass - usWeightClass);
563 anDiff[3] = abs((pFM[i].fsSelection & 0x2f) - fsSelection);
564 if(anDiff[0] == 0)
565 {
cc95f4f9
DW
566 if( (nIs & 0x01) == 0)
567 {
568 nIs = 1;
569 nIndex = i;
570 anMinDiff[1] = anDiff[1];
571 anMinDiff[2] = anDiff[2];
572 anMinDiff[3] = anDiff[3];
573 }
574 else if(anDiff[3] < anMinDiff[3])
575 {
576 nIndex = i;
577 anMinDiff[3] = anDiff[3];
578 }
579 else if(anDiff[2] < anMinDiff[2])
580 {
581 nIndex = i;
582 anMinDiff[2] = anDiff[2];
583 }
584 else if(anDiff[1] < anMinDiff[1])
585 {
586 nIndex = i;
587 anMinDiff[1] = anDiff[1];
588 }
589 anMinDiff[0] = 0;
590 }
591 else if(anDiff[0] < anMinDiff[0])
592 {
593 nIs = 2;
594 nIndex = i;
595 anMinDiff[3] = anDiff[3];
596 anMinDiff[2] = anDiff[2];
597 anMinDiff[1] = anDiff[1];
598 anMinDiff[0] = anDiff[0];
599 }
600 else if(anDiff[0] == anMinDiff[0])
601 {
602 if(anDiff[3] < anMinDiff[3])
603 {
604 nIndex = i;
605 anMinDiff[3] = anDiff[3];
606 nIs = 2;
607 }
608 else if(anDiff[2] < anMinDiff[2])
609 {
610 nIndex = i;
611 anMinDiff[2] = anDiff[2];
612 nIs = 2;
613 }
614 else if(anDiff[1] < anMinDiff[1])
615 {
616 nIndex = i;
617 anMinDiff[1] = anDiff[1];
618 nIs = 2;
619 }
620 }
d8cde57b 621 }
d8cde57b 622
e99762c0 623 //
cc95f4f9 624 // Fill in the FATTRS with the best match from FONTMETRICS
e99762c0 625 //
a23692f0 626 pFattrs->usRecordLength = sizeof(FATTRS); // Sets size of structure
a23692f0 627 pFattrs->lMatch = pFM[nIndex].lMatch; // Force match
f289196b
DW
628 pFattrs->idRegistry = 0;
629 pFattrs->usCodePage = 0;
630 pFattrs->fsFontUse = 0;
631 pFattrs->fsType = 0;
632 pFattrs->lMaxBaselineExt = 0;
633 pFattrs->lAveCharWidth = 0;
0fba44b4 634 wxStrcpy((wxChar*)pFattrs->szFacename, (wxChar*)pFM[nIndex].szFacename);
a4353f07
DW
635 if (pFont->GetWeight() == wxNORMAL)
636 pFattrs->fsSelection = 0;
637 else
638 pFattrs->fsSelection = FATTR_SEL_BOLD;
cc95f4f9 639
a4353f07 640 if (pFont->GetStyle() == wxITALIC || pFont->GetStyle() == wxSLANT)
cc95f4f9 641 pFattrs->fsSelection |= FATTR_SEL_ITALIC;
a4353f07
DW
642
643 if (pFont->GetUnderlined())
644 pFattrs->fsSelection |= FATTR_SEL_UNDERSCORE;
cc95f4f9 645} // end of wxOS2SelectMatchingFontByName
e99762c0
DW
646
647wxFont wxCreateFontFromLogFont(
648 const LOGFONT* pLogFont
649, const PFONTMETRICS pFM
650, PFACENAMEDESC pFaceName
651)
d8cde57b 652{
47df2b8c 653 wxNativeFontInfo vInfo;
d8cde57b 654
47df2b8c
DW
655 vInfo.fa = *pLogFont;
656 vInfo.fm = *pFM;
657 vInfo.fn = *pFaceName;
658 return wxFont(vInfo);
e99762c0
DW
659} // end of wxCreateFontFromLogFont
660
661int wxGpiStrcmp(
0fba44b4
DW
662 wxChar* s0
663, wxChar* s1
e99762c0
DW
664)
665{ int l0;
666 int l1;
667 int l;
668 int d;
669 int d1;
670 int i;
671 int rc;
672
673 rc = 0;
674 if(s0 == NULL)
675 {
676 if(s1 == NULL)
677 return 0;
678 else
679 return 32;
680 }
681 else if(s1 == NULL)
682 return 32;
683
0fba44b4
DW
684 l0 = wxStrlen(s0);
685 l1 = wxStrlen(s1);
e99762c0
DW
686 l = l0;
687 if(l0 != l1)
688 {
689 rc++;
690 if(l1 < l0)
691 l = l1;
692 }
693 for(i=0;i<l;i++)
694 {
695 d = s0[i]-s1[i];
696 if(!d)
697 continue;
0fba44b4 698 d1 = wxToupper(s0[i]) - wxToupper(s1[i]);
e99762c0
DW
699 if(!d1)
700 continue;
701 rc += abs(d);
702 }
703 return rc;
d8cde57b 704}