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