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