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