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