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