]> git.saurik.com Git - wxWidgets.git/blame - src/common/object.cpp
warning (in Unicode only) fix
[wxWidgets.git] / src / common / object.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
b2edef6f 2// Name: src/common/object.cpp
c801d85f
KB
3// Purpose: wxObject implementation
4// Author: Julian Smart
0b9ab0bd 5// Modified by: Ron Lee
c801d85f
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) 1998 Julian Smart
0b9ab0bd 9// (c) 2001 Ron Lee <ron@debian.org>
55d99c7a 10// Licence: wxWindows licence
c801d85f
KB
11/////////////////////////////////////////////////////////////////////////////
12
13#ifdef __GNUG__
14#pragma implementation "object.h"
15#endif
16
b2edef6f 17// For compilers that support precompilation, includes "wx.h".
c801d85f
KB
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21#pragma hdrstop
22#endif
23
1678ad78 24#ifndef WX_PRECOMP
0b9ab0bd 25#include "wx/hash.h"
24eb81cb
DW
26#endif
27
c801d85f 28#include <string.h>
c801d85f 29
ea57084d 30#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
c801d85f
KB
31#include "wx/memory.h"
32#endif
33
ea57084d 34#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
3f4a0c5b 35 // for wxObject::Dump
b2edef6f 36 #include "wx/ioswrap.h"
c801d85f 37
b2edef6f
VZ
38 #if defined(__VISAGECPP__)
39 #define DEBUG_PRINTF(NAME) { static int raz=0; \
40 printf( #NAME " %i\n",raz); fflush(stdout); raz++; }
41 #else
42 #define DEBUG_PRINTF(NAME)
43 #endif
44#endif // __WXDEBUG__ || wxUSE_DEBUG_CONTEXT
c801d85f 45
e1720942
VZ
46// we must disable optimizations for VC.NET because otherwise its too eager
47// linker discards wxClassInfo objects in release build thus breaking many,
48// many things
fbae49ee 49#if defined __VISUALC__ && __VISUALC__ >= 1300
e1720942
VZ
50 #pragma optimize("", off)
51#endif
f6bcfd97 52
0b9ab0bd
RL
53wxClassInfo wxObject::sm_classwxObject( wxT("wxObject"), 0, 0,
54 (int) sizeof(wxObject),
55 (wxObjectConstructorFn) 0 );
c801d85f 56
e1720942 57// restore optimizations
fbae49ee 58#if defined __VISUALC__ && __VISUALC__ >= 1300
e1720942
VZ
59 #pragma optimize("", on)
60#endif
61
b2edef6f
VZ
62wxClassInfo* wxClassInfo::sm_first = NULL;
63wxHashTable* wxClassInfo::sm_classTable = NULL;
c801d85f 64
b2edef6f
VZ
65// These are here so we can avoid 'always true/false' warnings
66// by referring to these instead of TRUE/FALSE
0b9ab0bd
RL
67const bool wxTrue = TRUE;
68const bool wxFalse = FALSE;
c801d85f 69
b2edef6f
VZ
70// Is this object a kind of (a subclass of) 'info'?
71// E.g. is wxWindow a kind of wxObject?
72// Go from this class to superclass, taking into account
73// two possible base classes.
341287bf 74bool wxObject::IsKindOf(wxClassInfo *info) const
c801d85f 75{
afb74891 76 wxClassInfo *thisInfo = GetClassInfo();
0b9ab0bd 77 return (thisInfo) ? thisInfo->IsKindOf(info) : FALSE ;
c801d85f
KB
78}
79
38830220 80#if wxUSE_STD_IOSTREAM && (defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT)
dd107c50 81void wxObject::Dump(wxSTD ostream& str)
c801d85f 82{
afb74891
VZ
83 if (GetClassInfo() && GetClassInfo()->GetClassName())
84 str << GetClassInfo()->GetClassName();
85 else
b2edef6f 86 str << _T("unknown object class");
c801d85f
KB
87}
88#endif
89
c801d85f 90
cf760e4c
VZ
91#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING && defined( new )
92 #undef new
93#endif
94
95
b2edef6f 96#ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT
cf760e4c 97void *wxObject::operator new ( size_t size, const wxChar *fileName, int lineNum )
c801d85f 98{
cf760e4c 99 return wxDebugAlloc(size, (wxChar*) fileName, lineNum, TRUE);
c801d85f 100}
b2edef6f 101#endif
c801d85f 102
b2edef6f
VZ
103#ifdef _WX_WANT_DELETE_VOID
104void wxObject::operator delete ( void *buf )
415ca026
DW
105{
106 wxDebugFree(buf);
107}
b2edef6f
VZ
108#endif
109
110#ifdef _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
111void wxObject::operator delete ( void *buf, const char *_fname, size_t _line )
c801d85f 112{
afb74891 113 wxDebugFree(buf);
c801d85f 114}
0b9ab0bd
RL
115#endif
116
b2edef6f 117#ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT
cf760e4c 118void wxObject::operator delete ( void *buf, const wxChar *WXUNUSED(fileName), int WXUNUSED(lineNum) )
76626af2 119{
b2edef6f 120 wxDebugFree(buf);
76626af2
JS
121}
122#endif
123
b2edef6f 124#ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
cf760e4c 125void *wxObject::operator new[] ( size_t size, const wxChar* fileName, int lineNum )
c801d85f 126{
cf760e4c 127 return wxDebugAlloc(size, (wxChar*) fileName, lineNum, TRUE, TRUE);
c801d85f 128}
b2edef6f 129#endif
c801d85f 130
b2edef6f
VZ
131#ifdef _WX_WANT_ARRAY_DELETE_VOID
132void wxObject::operator delete[] ( void *buf )
c801d85f 133{
afb74891 134 wxDebugFree(buf, TRUE);
c801d85f
KB
135}
136#endif
137
b2edef6f 138#ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
cf760e4c 139void wxObject::operator delete[] (void * buf, const wxChar* WXUNUSED(fileName), int WXUNUSED(lineNum) )
b2edef6f
VZ
140{
141 wxDebugFree(buf, TRUE);
142}
143#endif
afb74891 144
afb74891 145
0b9ab0bd
RL
146// ----------------------------------------------------------------------------
147// wxClassInfo
148// ----------------------------------------------------------------------------
c801d85f 149
aa4b7ef9
VZ
150wxClassInfo::~wxClassInfo()
151{
152 // remove this object from the linked list of all class infos: if we don't
153 // do it, loading/unloading a DLL containing static wxClassInfo objects is
154 // not going to work
155 if ( this == sm_first )
156 {
157 sm_first = m_next;
158 }
159 else
160 {
161 wxClassInfo *info = sm_first;
162 while (info)
163 {
164 if ( info->m_next == this )
165 {
166 info->m_next = m_next;
167 break;
168 }
169
170 info = info->m_next;
171 }
172 }
173}
174
0b9ab0bd 175wxClassInfo *wxClassInfo::FindClass(const wxChar *className)
c801d85f 176{
80e8062f
VZ
177 if ( sm_classTable )
178 {
179 return (wxClassInfo *)wxClassInfo::sm_classTable->Get(className);
180 }
181 else
182 {
183 for ( wxClassInfo *info = sm_first; info ; info = info->m_next )
184 {
185 if ( wxStrcmp(info->GetClassName(), className) == 0 )
186 return info;
187 }
188
189 return NULL;
190 }
c801d85f
KB
191}
192
1f428942
VZ
193// a tiny InitializeClasses() helper
194/* static */
195inline wxClassInfo *wxClassInfo::GetBaseByName(const wxChar *name)
196{
197 if ( !name )
198 return NULL;
199
200 wxClassInfo *classInfo = (wxClassInfo *)sm_classTable->Get(name);
201
27db95f0
VZ
202#ifdef __WXDEBUG__
203 // this must be fixed, other things will work wrongly later if you get this
204 if ( !classInfo )
205 {
206 wxFAIL_MSG( wxString::Format
207 (
208 _T("base class '%s' is unknown to wxWindows RTTI"),
209 name
210 ) );
211 }
212#endif // __WXDEBUG__
1f428942
VZ
213
214 return classInfo;
215}
c801d85f 216
1f428942 217// Set pointers to base class(es) to speed up IsKindOf
afb74891 218void wxClassInfo::InitializeClasses()
c801d85f 219{
309689b2
VZ
220 // using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you
221 // link any object module twice mistakenly) will break this function
222 // because it will enter an infinite loop and eventually die with "out of
223 // memory" - as this is quite hard to detect if you're unaware of this,
224 // try to do some checks here
0b9ab0bd 225
309689b2 226#ifdef __WXDEBUG__
0b9ab0bd 227 static const size_t nMaxClasses = 10000; // more than we'll ever have
309689b2 228 size_t nClass = 0;
0b9ab0bd 229#endif
309689b2 230
edf0993c 231 sm_classTable = new wxHashTable(wxKEY_STRING);
afb74891 232
0b9ab0bd
RL
233 // Index all class infos by their class name
234
235 wxClassInfo *info;
236 for(info = sm_first; info; info = info->m_next)
afb74891
VZ
237 {
238 if (info->m_className)
309689b2
VZ
239 {
240 wxASSERT_MSG( ++nClass < nMaxClasses,
f6bcfd97 241 _T("an infinite loop detected - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be by linking some object module(s) twice)?") );
afb74891 242 sm_classTable->Put(info->m_className, (wxObject *)info);
309689b2 243 }
afb74891
VZ
244 }
245
0b9ab0bd
RL
246 // Set base pointers for each wxClassInfo
247
248 for(info = sm_first; info; info = info->m_next)
afb74891 249 {
1f428942
VZ
250 info->m_baseInfo1 = GetBaseByName(info->GetBaseClassName1());
251 info->m_baseInfo2 = GetBaseByName(info->GetBaseClassName2());
afb74891 252 }
c801d85f
KB
253}
254
afb74891 255void wxClassInfo::CleanUpClasses()
c801d85f 256{
0c32066b 257 delete wxClassInfo::sm_classTable;
b2edef6f 258 wxClassInfo::sm_classTable = NULL;
0c32066b 259}
f4a8c29f 260
0b9ab0bd 261
cf2f341a 262wxObject *wxCreateDynamicObject(const wxChar *name)
0c32066b 263{
bbee61e5 264#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
b2edef6f 265 DEBUG_PRINTF(wxObject *wxCreateDynamicObject)
bbee61e5 266#endif
61cca9d2 267
b2edef6f 268 if ( wxClassInfo::sm_classTable )
0c32066b
JS
269 {
270 wxClassInfo *info = (wxClassInfo *)wxClassInfo::sm_classTable->Get(name);
b2edef6f 271 return info ? info->CreateObject() : NULL;
0c32066b 272 }
b2edef6f 273 else // no sm_classTable yet
0c32066b 274 {
b2edef6f
VZ
275 for ( wxClassInfo *info = wxClassInfo::sm_first;
276 info;
277 info = info->m_next )
278 {
cf2f341a 279 if (info->m_className && wxStrcmp(info->m_className, name) == 0)
0c32066b 280 return info->CreateObject();
b2edef6f
VZ
281 }
282
283 return NULL;
0c32066b 284 }
c801d85f
KB
285}
286
7a4b9130 287
0b9ab0bd 288// ----------------------------------------------------------------------------
a6391d30 289// wxObject
0b9ab0bd 290// ----------------------------------------------------------------------------
c801d85f 291
a6391d30
GD
292// Initialize ref data from another object (needed for copy constructor and
293// assignment operator)
294void wxObject::InitFrom(const wxObject& other)
295{
296 m_refData = other.m_refData;
297 if ( m_refData )
298 m_refData->m_count++;
299}
300
c801d85f
KB
301void wxObject::Ref(const wxObject& clone)
302{
bbee61e5 303#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
807d8487 304 DEBUG_PRINTF(wxObject::Ref)
bbee61e5 305#endif
0b9ab0bd 306
c89f5c02
RR
307 // nothing to be done
308 if (m_refData == clone.m_refData)
309 return;
310
0b9ab0bd 311 // delete reference to old data
c801d85f 312 UnRef();
0b9ab0bd 313
c801d85f 314 // reference new data
807d8487 315 if ( clone.m_refData )
0b9ab0bd 316 {
c801d85f
KB
317 m_refData = clone.m_refData;
318 ++(m_refData->m_count);
319 }
320}
321
afb74891 322void wxObject::UnRef()
c801d85f 323{
807d8487 324 if ( m_refData )
4fe5383d
VZ
325 {
326 wxASSERT_MSG( m_refData->m_count > 0, _T("invalid ref data count") );
327
328 if ( !--m_refData->m_count )
c801d85f 329 delete m_refData;
807d8487 330 m_refData = NULL;
c801d85f 331 }
c801d85f
KB
332}
333
807d8487
VZ
334void wxObject::AllocExclusive()
335{
336 if ( !m_refData )
337 {
338 m_refData = CreateRefData();
339 }
340 else if ( m_refData->GetRefCount() > 1 )
341 {
342 // note that ref is not going to be destroyed in this case
a9bf8315 343 const wxObjectRefData* ref = m_refData;
807d8487
VZ
344 UnRef();
345
346 // ... so we can still access it
347 m_refData = CloneRefData(ref);
348 }
349 //else: ref count is 1, we are exclusive owners of m_refData anyhow
350
351 wxASSERT_MSG( m_refData && m_refData->GetRefCount() == 1,
352 _T("wxObject::AllocExclusive() failed.") );
353}
354
355wxObjectRefData *wxObject::CreateRefData() const
356{
d1870078
VZ
357 // if you use AllocExclusive() you must override this method
358 wxFAIL_MSG( _T("CreateRefData() must be overridden if called!") );
359
807d8487
VZ
360 return NULL;
361}
362
a9bf8315
VZ
363wxObjectRefData *
364wxObject::CloneRefData(const wxObjectRefData * WXUNUSED(data)) const
807d8487 365{
d1870078
VZ
366 // if you use AllocExclusive() you must override this method
367 wxFAIL_MSG( _T("CloneRefData() must be overridden if called!") );
368
807d8487
VZ
369 return NULL;
370}
371
372// ----------------------------------------------------------------------------
373// misc
374// ----------------------------------------------------------------------------
ce28b4d7 375
edf0993c 376#if defined(__DARWIN__) && defined(WXMAKINGDLL)
ce28b4d7
GD
377
378extern "C" {
379 void __initialize_Cplusplus(void);
380 void wxWindowsDylibInit(void);
381};
382
edf0993c
GD
383// Dynamic shared library (dylib) initialization routine
384// required to initialize static C++ objects bacause of lazy dynamic linking
385// http://developer.apple.com/techpubs/macosx/Essentials/
386// SystemOverview/Frameworks/Dynamic_Shared_Libraries.html
0b9ab0bd 387
ce28b4d7
GD
388void wxWindowsDylibInit()
389{
390 // The function __initialize_Cplusplus() must be called from the shared
391 // library initialization routine to cause the static C++ objects in
392 // the library to be initialized (reference number 2441683).
393
edf0993c
GD
394 // This only seems to be necessary if the library initialization routine
395 // needs to use the static C++ objects
ce28b4d7
GD
396 __initialize_Cplusplus();
397}
398
399#endif
0b9ab0bd
RL
400
401// vi:sts=4:sw=4:et