OS/2 updates for statusbar processing and easier VA debugging
[wxWidgets.git] / src / os2 / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose: wxFont class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/06/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 #define DEBUG_PRINTF(NAME) { static int raz=0; \
12 printf( #NAME " %i\n",raz); fflush(stdout); \
13 raz++; \
14 }
15
16 #include <malloc.h>
17 #include <stdio.h>
18
19 int HeapCheck(void)
20 {
21 int rc;
22
23 if (_HEAPOK != (rc = _heapchk()))
24 {
25 switch(rc)
26 {
27 case _HEAPEMPTY:
28 puts("The heap has not been initialized.");
29 break;
30 case _HEAPBADNODE:
31 puts("A memory node is corrupted or the heap is damaged.");
32 break;
33 case _HEAPBADBEGIN:
34 puts("The heap specified is not valid.");
35 break;
36 }
37 fflush(stdout);
38 }
39 return 0;
40 }
41
42 // ============================================================================
43 // declarations
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // headers
48 // ----------------------------------------------------------------------------
49
50 #include <malloc.h>
51 // For compilers that support precompilation, includes "wx.h".
52 #include "wx/wxprec.h"
53
54 #ifndef WX_PRECOMP
55 #include <stdio.h>
56 #include "wx/setup.h"
57 #include "wx/list.h"
58 #include "wx/utils.h"
59 #include "wx/app.h"
60 #include "wx/font.h"
61 #endif // WX_PRECOMP
62
63 #include "wx/os2/private.h"
64
65 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
66
67 #if wxUSE_PORTABLE_FONTS_IN_MSW
68 IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
69 #endif
70
71 // ----------------------------------------------------------------------------
72 // wxFontRefData - the internal description of the font
73 // ----------------------------------------------------------------------------
74
75 class WXDLLEXPORT wxFontRefData: public wxGDIRefData
76 {
77 friend class WXDLLEXPORT wxFont;
78
79 public:
80 wxFontRefData()
81 {
82 Init(12, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
83 "", wxFONTENCODING_DEFAULT);
84 }
85
86 wxFontRefData(const wxFontRefData& data)
87 {
88 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
89 data.m_underlined, data.m_faceName, data.m_encoding);
90
91 m_fontId = data.m_fontId;
92 }
93
94 wxFontRefData(int size,
95 int family,
96 int style,
97 int weight,
98 bool underlined,
99 const wxString& faceName,
100 wxFontEncoding encoding)
101 {
102 Init(size, family, style, weight, underlined, faceName, encoding);
103 }
104
105 virtual ~wxFontRefData();
106
107 protected:
108 // common part of all ctors
109 void Init(int size,
110 int family,
111 int style,
112 int weight,
113 bool underlined,
114 const wxString& faceName,
115 wxFontEncoding encoding);
116
117 // If TRUE, the pointer to the actual font is temporary and SHOULD NOT BE
118 // DELETED by destructor
119 bool m_temporary;
120
121 int m_fontId;
122
123 // font characterstics
124 int m_pointSize;
125 int m_family;
126 int m_style;
127 int m_weight;
128 bool m_underlined;
129 wxString m_faceName;
130 wxFontEncoding m_encoding;
131
132 // Windows font handle
133 WXHFONT m_hFont;
134 };
135
136 // ============================================================================
137 // implementation
138 // ============================================================================
139
140 // ----------------------------------------------------------------------------
141 // wxFontRefData
142 // ----------------------------------------------------------------------------
143
144 void wxFontRefData::Init(int pointSize,
145 int family,
146 int style,
147 int weight,
148 bool underlined,
149 const wxString& faceName,
150 wxFontEncoding encoding)
151 {
152 m_style = style;
153 m_pointSize = pointSize;
154 m_family = family;
155 m_style = style;
156 m_weight = weight;
157 m_underlined = underlined;
158 m_faceName = faceName;
159 m_encoding = encoding;
160
161 m_fontId = 0;
162 m_temporary = FALSE;
163
164 m_hFont = 0;
165 }
166
167 wxFontRefData::~wxFontRefData()
168 {
169 DEBUG_PRINTF(wxFontRefData::~wxFontRefData!!!)
170 // TODO:
171 // if ( m_hFont )
172 // {
173 // if ( !::DeleteObject((HFONT) m_hFont) )
174 // {
175 // wxLogLastError("DeleteObject(font)");
176 // }
177 // }
178 }
179
180 // ----------------------------------------------------------------------------
181 // wxFont
182 // ----------------------------------------------------------------------------
183
184 void wxFont::Init()
185 {
186
187 DEBUG_PRINTF(wxFontRefData::~wxFontRefData!!!)
188
189 if ( wxTheFontList )
190 wxTheFontList->Append(this);
191 }
192
193 /* Constructor for a font. Note that the real construction is done
194 * in wxDC::SetFont, when information is available about scaling etc.
195 */
196 bool wxFont::Create(int pointSize,
197 int family,
198 int style,
199 int weight,
200 bool underlined,
201 const wxString& faceName,
202 wxFontEncoding encoding)
203 {
204 UnRef();
205 DEBUG_PRINTF(wxFontRefData::~wxFontRefData!!!)
206 m_refData = new wxFontRefData(pointSize, family, style, weight,
207 underlined, faceName, encoding);
208
209 RealizeResource();
210
211 return TRUE;
212 }
213
214 wxFont::~wxFont()
215 {
216 int l;
217 l = sizeof(*this);
218 HeapCheck();
219 _heap_check();
220
221 if ( wxTheFontList )
222 wxTheFontList->DeleteObject(this);
223 HeapCheck();
224 _heap_check();
225
226 }
227
228 // ----------------------------------------------------------------------------
229 // real implementation
230 // Boris' Kovalenko comments:
231 // Because OS/2 fonts are associated with PS we can not create the font
232 // here, but we may check that font definition is true
233 // ----------------------------------------------------------------------------
234
235 bool wxFont::RealizeResource()
236 {
237 DEBUG_PRINTF(wxFont::RealizeResource)
238 if ( GetResourceHandle() )
239 {
240 // VZ: the old code returned FALSE in this case, but it doesn't seem
241 // to make sense because the font _was_ created
242 wxLogDebug(wxT("Calling wxFont::RealizeResource() twice"));
243
244 return TRUE;
245 }
246
247 HPS hps;
248 FATTRS fAttrs;
249 FACENAMEDESC fName;
250 LONG fLid;
251
252 fAttrs.usRecordLength = sizeof(FATTRS);
253 fAttrs.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
254 FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
255 fAttrs.fsType = 0;
256 fAttrs.lMaxBaselineExt = fAttrs.lAveCharWidth = 0;
257 fAttrs.idRegistry = 0;
258 fAttrs.lMatch = 0;
259
260 fName.usSize = sizeof(FACENAMEDESC);
261 fName.usWidthClass = FWIDTH_NORMAL;
262 fName.usReserved = 0;
263 fName.flOptions = 0;
264
265 wxString ff_face;
266
267 // OS/2 combines the family with styles to give a facename
268
269 switch ( M_FONTDATA->m_family )
270 {
271 case wxSCRIPT:
272 case wxDECORATIVE:
273 case wxROMAN:
274 ff_face = wxT("Times New Roman") ;
275 break;
276
277 case wxTELETYPE:
278 case wxMODERN:
279 ff_face = wxT("Courier") ;
280 break;
281
282 case wxSWISS:
283 case wxDEFAULT:
284 default:
285 ff_face = wxT("Helvetica") ;
286 }
287
288 switch ( M_FONTDATA->m_style )
289 {
290 case wxITALIC:
291 case wxSLANT:
292 fAttrs.fsSelection = FATTR_SEL_ITALIC;
293 break;
294
295 default:
296 wxFAIL_MSG(wxT("unknown font slant"));
297 // fall through
298
299 case wxNORMAL:
300 fAttrs.fsSelection = 0;
301 }
302
303 switch ( M_FONTDATA->m_weight )
304 {
305 default:
306 wxFAIL_MSG(wxT("unknown font weight"));
307 // fall through
308
309 case wxNORMAL:
310 fName.usWeightClass = FWEIGHT_NORMAL;
311 break;
312
313 case wxLIGHT:
314 fName.usWeightClass = FWEIGHT_LIGHT;
315 break;
316
317 case wxBOLD:
318 fName.usWeightClass = FWEIGHT_BOLD;
319 break;
320 }
321
322 if( M_FONTDATA->m_underlined )
323 fAttrs.fsSelection |= FATTR_SEL_UNDERSCORE;
324
325 wxFontEncoding encoding = M_FONTDATA->m_encoding;
326 if ( encoding == wxFONTENCODING_DEFAULT )
327 {
328 encoding = wxFont::GetDefaultEncoding();
329 }
330
331 switch ( encoding )
332 {
333 case wxFONTENCODING_ISO8859_1:
334 case wxFONTENCODING_ISO8859_15:
335 case wxFONTENCODING_CP1250:
336 fAttrs.usCodePage = 1250;
337 break;
338
339 case wxFONTENCODING_ISO8859_2:
340 case wxFONTENCODING_CP1252:
341 fAttrs.usCodePage = 1252;
342 break;
343
344 case wxFONTENCODING_ISO8859_4:
345 case wxFONTENCODING_ISO8859_10:
346 fAttrs.usCodePage = 850; // what is baltic?
347 break;
348
349 case wxFONTENCODING_ISO8859_5:
350 case wxFONTENCODING_CP1251:
351 fAttrs.usCodePage = 1251;
352 break;
353
354 case wxFONTENCODING_ISO8859_6:
355 fAttrs.usCodePage = 850; // what is arabic?
356 break;
357
358 case wxFONTENCODING_ISO8859_7:
359 fAttrs.usCodePage = 850; // what is greek
360 break;
361
362 case wxFONTENCODING_ISO8859_8:
363 fAttrs.usCodePage = 850; // what is hebrew?
364 break;
365
366 case wxFONTENCODING_ISO8859_9:
367 fAttrs.usCodePage = 857;
368 break;
369
370 case wxFONTENCODING_ISO8859_11:
371 fAttrs.usCodePage = 850; // what is thai
372 break;
373
374 case wxFONTENCODING_CP437:
375 fAttrs.usCodePage = 437;
376 break;
377
378 default:
379 wxFAIL_MSG(wxT("unsupported encoding"));
380 // fall through
381
382 case wxFONTENCODING_SYSTEM:
383 fAttrs.usCodePage = 850; // what is ANSI?
384 break;
385 }
386
387 // Now cheking
388 fLid = 1;
389 hps = ::WinGetPS( HWND_DESKTOP );
390
391 long numLids = ::GpiQueryNumberSetIds( hps );
392 long gpiError;
393
394 // First we should generate unique id
395 if( numLids )
396 {
397 long Types[255];
398 STR8 Names[255];
399 long lIds[255];
400
401 if( !GpiQuerySetIds(hps, numLids, Types, Names, lIds) )
402 {
403 ::WinReleasePS( hps );
404 return 0;
405 }
406
407 for(unsigned long LCNum = 0; LCNum < numLids; LCNum++)
408 if(lIds[LCNum] == fLid)
409 ++fLid;
410 if(fLid > 254) // wow, no id available!
411 {
412 ::WinReleasePS( hps );
413 return 0;
414 }
415 }
416
417 // now building facestring
418 if(::GpiQueryFaceString(hps, ff_face.c_str(), &fName, FACESIZE, fAttrs.szFacename) == GPI_ERROR)
419 {
420 ::WinReleasePS( hps );
421 return 0;
422 }
423
424 // now creating font
425 WXHFONT hFont = (WXHFONT)0;
426
427 if(::GpiCreateLogFont(hps, NULL, fLid, &fAttrs) != GPI_ERROR)
428 M_FONTDATA->m_hFont = hFont = (WXHFONT)1;
429
430 if( hFont )
431 ::GpiDeleteSetId(hps, fLid);
432
433 ::WinReleasePS( hps );
434
435 if ( !hFont )
436 {
437 wxLogLastError("CreateFont");
438 }
439
440 return hFont != 0;
441 }
442
443 bool wxFont::FreeResource(bool force)
444 {
445 if ( GetResourceHandle() )
446 {
447 // TODO:
448 // if ( !::DeleteObject((HFONT) M_FONTDATA->m_hFont) )
449 // {
450 // wxLogLastError("DeleteObject(font)");
451 // }
452
453 M_FONTDATA->m_hFont = 0;
454
455 return TRUE;
456 }
457 return FALSE;
458 }
459
460 WXHANDLE wxFont::GetResourceHandle()
461 {
462 if ( !M_FONTDATA )
463 return 0;
464 else
465 return (WXHANDLE)M_FONTDATA->m_hFont ;
466 }
467
468 bool wxFont::IsFree() const
469 {
470 return (M_FONTDATA && (M_FONTDATA->m_hFont == 0));
471 }
472
473 void wxFont::Unshare()
474 {
475 // Don't change shared data
476 if ( !m_refData )
477 {
478 m_refData = new wxFontRefData();
479 }
480 else
481 {
482 wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
483 UnRef();
484 m_refData = ref;
485 }
486 }
487
488 // ----------------------------------------------------------------------------
489 // change font attribute: we recreate font when doing it
490 // ----------------------------------------------------------------------------
491
492 void wxFont::SetPointSize(int pointSize)
493 {
494 Unshare();
495
496 M_FONTDATA->m_pointSize = pointSize;
497
498 RealizeResource();
499 }
500
501 void wxFont::SetFamily(int family)
502 {
503 Unshare();
504
505 M_FONTDATA->m_family = family;
506
507 RealizeResource();
508 }
509
510 void wxFont::SetStyle(int style)
511 {
512 Unshare();
513
514 M_FONTDATA->m_style = style;
515
516 RealizeResource();
517 }
518
519 void wxFont::SetWeight(int weight)
520 {
521 Unshare();
522
523 M_FONTDATA->m_weight = weight;
524
525 RealizeResource();
526 }
527
528 void wxFont::SetFaceName(const wxString& faceName)
529 {
530 Unshare();
531
532 M_FONTDATA->m_faceName = faceName;
533
534 RealizeResource();
535 }
536
537 void wxFont::SetUnderlined(bool underlined)
538 {
539 Unshare();
540
541 M_FONTDATA->m_underlined = underlined;
542
543 RealizeResource();
544 }
545
546 void wxFont::SetEncoding(wxFontEncoding encoding)
547 {
548 Unshare();
549
550 M_FONTDATA->m_encoding = encoding;
551
552 RealizeResource();
553 }
554
555 // ----------------------------------------------------------------------------
556 // accessors
557 // ----------------------------------------------------------------------------
558
559 int wxFont::GetPointSize() const
560 {
561 DEBUG_PRINTF(wxFont::GetPointSize)
562 wxFontRefData* pTmp;
563
564 pTmp = M_FONTDATA;
565 if(pTmp)
566 return pTmp->m_pointSize;
567 else
568 return 10;
569 }
570
571 int wxFont::GetFamily() const
572 {
573 return M_FONTDATA->m_family;
574 }
575
576 int wxFont::GetFontId() const
577 {
578 return M_FONTDATA->m_fontId;
579 }
580
581 int wxFont::GetStyle() const
582 {
583 return M_FONTDATA->m_style;
584 }
585
586 int wxFont::GetWeight() const
587 {
588 return M_FONTDATA->m_weight;
589 }
590
591 bool wxFont::GetUnderlined() const
592 {
593 return M_FONTDATA->m_underlined;
594 }
595
596 wxString wxFont::GetFaceName() const
597 {
598 wxString str;
599 if ( M_FONTDATA )
600 str = M_FONTDATA->m_faceName ;
601 return str;
602 }
603
604 wxFontEncoding wxFont::GetEncoding() const
605 {
606 return M_FONTDATA->m_encoding;
607 }
608