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