]> git.saurik.com Git - wxWidgets.git/blame - src/common/object.cpp
minor fix that was part of helpbest.patch
[wxWidgets.git] / src / common / object.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: object.cpp
3// Purpose: wxObject implementation
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
3f4a0c5b 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "object.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
1678ad78 23#ifndef WX_PRECOMP
794df945 24 #include "wx/hash.h"
1ccbb61a 25 #if wxUSE_SERIAL
794df945
VZ
26 #include "wx/objstrm.h"
27 #include "wx/serbase.h"
28
29 // for error messages
30 #include "wx/log.h"
31 #include "wx/intl.h"
32 #endif // wxUSE_SERIAL
33#endif // WX_PRECOMP
c801d85f
KB
34
35#include <string.h>
36#include <assert.h>
37
ea57084d 38#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
c801d85f
KB
39#include "wx/memory.h"
40#endif
41
ea57084d 42#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
3f4a0c5b
VZ
43 // for wxObject::Dump
44 #include "wx/ioswrap.h"
415ca026
DW
45 #if defined(__VISAGECPP__)
46 // help with VA debugging
47 #define DEBUG_PRINTF(NAME) { static int raz=0; \
48 printf( #NAME " %i\n",raz); fflush(stdout); \
49 raz++; \
50 }
51 #else
52 #define DEBUG_PRINTF(NAME)
53 #endif
c801d85f
KB
54#endif
55
223d09f6 56wxClassInfo wxObject::sm_classwxObject((wxChar *) wxT("wxObject"), (wxChar *) NULL, (wxChar *) NULL, (int ) sizeof(wxObject), (wxObjectConstructorFn) NULL);
0c32066b
JS
57wxClassInfo* wxClassInfo::sm_first = (wxClassInfo *) NULL;
58wxHashTable* wxClassInfo::sm_classTable = (wxHashTable*) NULL;
c801d85f 59
f6bcfd97
BP
60// These are here so we can avoid 'always true/false' warnings
61// by referring to these instead of TRUE/FALSE
62const bool wxTrue = TRUE;
63const bool wxFalse = FALSE;
64
c801d85f
KB
65/*
66 * wxWindows root object.
67 */
68
afb74891 69wxObject::wxObject()
c801d85f 70{
afb74891 71 m_refData = (wxObjectRefData *) NULL;
1ccbb61a 72#if wxUSE_SERIAL
afb74891 73 m_serialObj = (wxObject_Serialize *)NULL;
f4a8c29f 74#endif
c801d85f
KB
75}
76
afb74891 77wxObject::~wxObject()
c801d85f 78{
afb74891 79 UnRef();
1ccbb61a 80#if wxUSE_SERIAL
afb74891
VZ
81 if (m_serialObj)
82 delete m_serialObj;
f4a8c29f 83#endif
c801d85f
KB
84}
85
86/*
87 * Is this object a kind of (a subclass of) 'info'?
88 * E.g. is wxWindow a kind of wxObject?
89 * Go from this class to superclass, taking into account
90 * two possible base classes.
91 */
afb74891 92
341287bf 93bool wxObject::IsKindOf(wxClassInfo *info) const
c801d85f 94{
afb74891
VZ
95 wxClassInfo *thisInfo = GetClassInfo();
96 if (thisInfo)
97 return thisInfo->IsKindOf(info);
98 else
99 return FALSE;
c801d85f
KB
100}
101
a737331d
GL
102wxObject *wxObject::Clone() const
103{
aadbdf11
GL
104 wxObject *object = GetClassInfo()->CreateObject();
105 CopyObject(*object);
106 return object;
107}
108
72cdf4c9 109#ifdef __WXDEBUG__
aadbdf11 110void wxObject::CopyObject(wxObject& object_dest) const
72cdf4c9
VZ
111#else // !Debug
112void wxObject::CopyObject(wxObject& WXUNUSED(object_dest)) const
113#endif // Debug/!Debug
aadbdf11
GL
114{
115 wxASSERT(object_dest.GetClassInfo()->IsKindOf(GetClassInfo()));
a737331d
GL
116}
117
38830220 118#if wxUSE_STD_IOSTREAM && (defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT)
dd107c50 119void wxObject::Dump(wxSTD ostream& str)
c801d85f 120{
afb74891
VZ
121 if (GetClassInfo() && GetClassInfo()->GetClassName())
122 str << GetClassInfo()->GetClassName();
123 else
124 str << "unknown object class";
c801d85f
KB
125}
126#endif
127
ea57084d 128#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING
c801d85f
KB
129
130#ifdef new
131#undef new
132#endif
133
4de6207a 134void *wxObject::operator new (size_t size, wxChar * fileName, int lineNum)
c801d85f 135{
afb74891 136 return wxDebugAlloc(size, fileName, lineNum, TRUE);
c801d85f
KB
137}
138
415ca026
DW
139#if defined(__VISAGECPP__)
140# if __DEBUG_ALLOC__
141void wxObject::operator delete (void * buf,const char * _fname, size_t _line)
142{
143 wxDebugFree(buf);
144}
145# endif //__DEBUG_ALLOC__
146#else
c801d85f
KB
147void wxObject::operator delete (void * buf)
148{
afb74891 149 wxDebugFree(buf);
c801d85f 150}
415ca026 151#endif // __VISAGECPP__
c801d85f 152
76626af2 153// VC++ 6.0
3f4a0c5b 154#if defined(__VISUALC__) && (__VISUALC__ >= 1200)
f6bcfd97 155void wxObject::operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
76626af2 156{
afb74891 157 ::operator delete(pData);
76626af2
JS
158}
159#endif
160
c801d85f 161// Cause problems for VC++ - crashes
7c74e7fe 162#if (!defined(__VISUALC__) && wxUSE_ARRAY_MEMORY_OPERATORS ) || defined(__MWERKS__)
4de6207a 163void * wxObject::operator new[] (size_t size, wxChar * fileName, int lineNum)
c801d85f 164{
afb74891 165 return wxDebugAlloc(size, fileName, lineNum, TRUE, TRUE);
c801d85f
KB
166}
167
168void wxObject::operator delete[] (void * buf)
169{
afb74891 170 wxDebugFree(buf, TRUE);
c801d85f
KB
171}
172#endif
173
174#endif
175
176/*
177 * Class info: provides run-time class type information.
178 */
179
6057972b
VZ
180wxClassInfo::wxClassInfo(const wxChar *cName,
181 const wxChar *baseName1,
182 const wxChar *baseName2,
183 int sz,
184 wxObjectConstructorFn constr)
c801d85f 185{
afb74891
VZ
186 m_className = cName;
187 m_baseClassName1 = baseName1;
188 m_baseClassName2 = baseName2;
189
190 m_objectSize = sz;
191 m_objectConstructor = constr;
192
193 m_next = sm_first;
194 sm_first = this;
195
196 m_baseInfo1 = (wxClassInfo *) NULL;
197 m_baseInfo2 = (wxClassInfo *) NULL;
c801d85f
KB
198}
199
afb74891 200wxObject *wxClassInfo::CreateObject()
c801d85f 201{
afb74891
VZ
202 if (m_objectConstructor)
203 return (wxObject *)(*m_objectConstructor)();
204 else
205 return (wxObject *) NULL;
c801d85f
KB
206}
207
6057972b 208wxClassInfo *wxClassInfo::FindClass(const wxChar *c)
c801d85f 209{
afb74891
VZ
210 wxClassInfo *p = sm_first;
211 while (p)
212 {
6057972b
VZ
213 if ( wxStrcmp(p->GetClassName(), c) == 0 )
214 break;
215
afb74891
VZ
216 p = p->m_next;
217 }
6057972b
VZ
218
219 return p;
c801d85f
KB
220}
221
222// Climb upwards through inheritance hierarchy.
223// Dual inheritance is catered for.
6057972b 224bool wxClassInfo::IsKindOf(const wxClassInfo *info) const
c801d85f 225{
afb74891
VZ
226 if (info == NULL)
227 return FALSE;
228
afb74891
VZ
229 if (this == info)
230 return TRUE;
c801d85f 231
afb74891
VZ
232 if (m_baseInfo1)
233 if (m_baseInfo1->IsKindOf(info))
234 return TRUE;
c801d85f 235
afb74891
VZ
236 if (m_baseInfo2)
237 return m_baseInfo2->IsKindOf(info);
c801d85f 238
afb74891 239 return FALSE;
c801d85f
KB
240}
241
242// Set pointers to base class(es) to speed up IsKindOf
afb74891 243void wxClassInfo::InitializeClasses()
c801d85f 244{
309689b2
VZ
245 // using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you
246 // link any object module twice mistakenly) will break this function
247 // because it will enter an infinite loop and eventually die with "out of
248 // memory" - as this is quite hard to detect if you're unaware of this,
249 // try to do some checks here
250#ifdef __WXDEBUG__
251 // more classes than we'll ever have
252 static const size_t nMaxClasses = 10000;
253 size_t nClass = 0;
254#endif // Debug
255
afb74891
VZ
256 wxClassInfo::sm_classTable = new wxHashTable(wxKEY_STRING);
257
258 // Index all class infos by their class name
259 wxClassInfo *info = sm_first;
260 while (info)
261 {
262 if (info->m_className)
309689b2
VZ
263 {
264 wxASSERT_MSG( ++nClass < nMaxClasses,
f6bcfd97 265 _T("an infinite loop detected - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be by linking some object module(s) twice)?") );
309689b2 266
afb74891 267 sm_classTable->Put(info->m_className, (wxObject *)info);
309689b2
VZ
268 }
269
afb74891
VZ
270 info = info->m_next;
271 }
272
273 // Set base pointers for each wxClassInfo
274 info = sm_first;
275 while (info)
276 {
277 if (info->GetBaseClassName1())
278 info->m_baseInfo1 = (wxClassInfo *)sm_classTable->Get(info->GetBaseClassName1());
279 if (info->GetBaseClassName2())
280 info->m_baseInfo2 = (wxClassInfo *)sm_classTable->Get(info->GetBaseClassName2());
281 info = info->m_next;
282 }
c801d85f
KB
283}
284
afb74891 285void wxClassInfo::CleanUpClasses()
c801d85f 286{
0c32066b
JS
287 delete wxClassInfo::sm_classTable;
288 wxClassInfo::sm_classTable = NULL;
289}
f4a8c29f 290
cf2f341a 291wxObject *wxCreateDynamicObject(const wxChar *name)
0c32066b 292{
bbee61e5 293#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
415ca026 294 DEBUG_PRINTF(wxObject *wxCreateDynamicObject)
bbee61e5 295#endif
61cca9d2 296
0c32066b
JS
297 if (wxClassInfo::sm_classTable)
298 {
299 wxClassInfo *info = (wxClassInfo *)wxClassInfo::sm_classTable->Get(name);
300 if (!info)
301 return (wxObject *)NULL;
302
303 return info->CreateObject();
304 }
305 else
306 {
307 wxClassInfo *info = wxClassInfo::sm_first;
308 while (info)
309 {
cf2f341a 310 if (info->m_className && wxStrcmp(info->m_className, name) == 0)
0c32066b
JS
311 return info->CreateObject();
312 info = info->m_next;
313 }
314 return (wxObject*) NULL;
315 }
c801d85f
KB
316}
317
1ccbb61a 318#if wxUSE_SERIAL
c801d85f 319
7a4b9130
GL
320#include "wx/serbase.h"
321#include "wx/dynlib.h"
7a4b9130 322
1678ad78 323wxObject* wxCreateStoredObject( wxInputStream &stream )
c801d85f 324{
afb74891
VZ
325 wxObjectInputStream obj_s(stream);
326 return obj_s.LoadObject();
c801d85f
KB
327};
328
7a4b9130
GL
329void wxObject::StoreObject( wxObjectOutputStream& stream )
330{
bbee61e5 331#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
415ca026 332 DEBUG_PRINTF(wxObject::StoreObject)
bbee61e5 333#endif
61cca9d2 334
afb74891
VZ
335 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
336 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
7a4b9130 337
afb74891
VZ
338 if (!lib) {
339 wxLogError(_("Can't load wxSerial dynamic library."));
340 return;
341 }
f4a8c29f 342 if (!m_serialObj) {
afb74891
VZ
343 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
344
345 if (!m_serialObj) {
346 wxLogError(_("Can't find the serialization object '%s' "
347 "for the object '%s'."),
348 obj_name.c_str(),
349 GetClassInfo()->GetClassName());
350 return;
351 }
352 m_serialObj->SetObject(this);
f4a8c29f 353 }
7a4b9130 354
afb74891 355 m_serialObj->StoreObject(stream);
7a4b9130
GL
356}
357
358void wxObject::LoadObject( wxObjectInputStream& stream )
359{
bbee61e5 360#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
415ca026 361 DEBUG_PRINTF(wxObject::LoadObject)
bbee61e5 362#endif
61cca9d2 363
afb74891
VZ
364 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
365 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
7a4b9130 366
f4a8c29f 367 if (!m_serialObj) {
afb74891
VZ
368 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
369
370 if (!m_serialObj) {
371 wxLogError(_("Can't find the serialization object '%s' "
372 "for the object '%s'."),
373 obj_name.c_str(),
374 GetClassInfo()->GetClassName());
375 return;
376 }
377 m_serialObj->SetObject(this);
f4a8c29f 378 }
6f34921d 379
afb74891 380 m_serialObj->LoadObject(stream);
7a4b9130
GL
381}
382
bfc6fde4 383#endif // wxUSE_SERIAL
c801d85f
KB
384
385/*
386 * wxObject: cloning of objects
387 */
388
389void wxObject::Ref(const wxObject& clone)
390{
bbee61e5 391#if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
415ca026 392 DEBUG_PRINTF(wxObject::Ref)
bbee61e5
JJ
393#endif
394 // delete reference to old data
c801d85f
KB
395 UnRef();
396 // reference new data
397 if (clone.m_refData) {
398 m_refData = clone.m_refData;
399 ++(m_refData->m_count);
400 }
401}
402
afb74891 403void wxObject::UnRef()
c801d85f 404{
4fe5383d
VZ
405 if ( m_refData )
406 {
407 wxASSERT_MSG( m_refData->m_count > 0, _T("invalid ref data count") );
408
409 if ( !--m_refData->m_count )
c801d85f 410 delete m_refData;
4fe5383d 411 m_refData = (wxObjectRefData *) NULL;
c801d85f 412 }
c801d85f
KB
413}
414
415/*
416 * wxObjectData
417 */
418
419wxObjectRefData::wxObjectRefData(void) : m_count(1)
420{
421}
422
afb74891 423wxObjectRefData::~wxObjectRefData()
c801d85f
KB
424{
425}