New configure
[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_STORABLE_CLASSES
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::classwxObject((char *) "wxObject", (char *) NULL, (char *) NULL, (int ) sizeof(wxObject), (wxObjectConstructorFn) NULL);
45 wxClassInfo *wxClassInfo::first = (wxClassInfo *) NULL;
46 wxHashTable wxClassInfo::classTable(wxKEY_STRING);
47 #endif
48
49 /*
50 * wxWindows root object.
51 */
52
53 wxObject::wxObject(void)
54 {
55 m_refData = (wxObjectRefData *) NULL;
56 #ifdef USE_STORABLE_CLASSES
57 m_serialObj = (wxObject_Serialize *)NULL;
58 #endif
59 }
60
61 wxObject::~wxObject(void)
62 {
63 UnRef();
64 #ifdef USE_STORABLE_CLASSES
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)
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 // Cause problems for VC++ - crashes
113 #ifndef _MSC_VER
114 void * wxObject::operator new[] (size_t size, char * fileName, int lineNum)
115 {
116 return wxDebugAlloc(size, fileName, lineNum, TRUE, TRUE);
117 }
118
119 void wxObject::operator delete[] (void * buf)
120 {
121 wxDebugFree(buf, TRUE);
122 }
123 #endif
124
125 #endif
126
127 /*
128 * Class info: provides run-time class type information.
129 */
130
131 wxClassInfo::wxClassInfo(char *cName, char *baseName1, char *baseName2, int sz, wxObjectConstructorFn constr)
132 {
133 className = cName;
134 baseClassName1 = baseName1;
135 baseClassName2 = baseName2;
136
137 objectSize = sz;
138 objectConstructor = constr;
139
140 next = first;
141 first = this;
142
143 baseInfo1 = (wxClassInfo *) NULL;
144 baseInfo2 = (wxClassInfo *) NULL;
145 }
146
147 wxObject *wxClassInfo::CreateObject(void)
148 {
149 if (objectConstructor)
150 return (wxObject *)(*objectConstructor)();
151 else
152 return (wxObject *) NULL;
153 }
154
155 wxClassInfo *wxClassInfo::FindClass(char *c)
156 {
157 wxClassInfo *p = first;
158 while (p)
159 {
160 if (p && p->GetClassName() && strcmp(p->GetClassName(), c) == 0)
161 return p;
162 p = p->next;
163 }
164 return (wxClassInfo *) NULL;
165 }
166
167 // Climb upwards through inheritance hierarchy.
168 // Dual inheritance is catered for.
169 bool wxClassInfo::IsKindOf(wxClassInfo *info)
170 {
171 if (info == NULL)
172 return FALSE;
173
174 // For some reason, when making/using a DLL, static data has to be included
175 // in both the DLL and the application. This can lead to duplicate
176 // wxClassInfo objects, so we have to test the name instead of the pointers.
177 #if WXMAKINGDLL
178 if (GetClassName() && info->GetClassName() && (strcmp(GetClassName(), info->GetClassName()) == 0))
179 return TRUE;
180 #else
181 if (this == info)
182 return TRUE;
183 #endif
184
185 if (baseInfo1)
186 if (baseInfo1->IsKindOf(info))
187 return TRUE;
188
189 if (baseInfo2)
190 return baseInfo2->IsKindOf(info);
191
192 return FALSE;
193 }
194
195 // Set pointers to base class(es) to speed up IsKindOf
196 void wxClassInfo::InitializeClasses(void)
197 {
198 // Index all class infos by their class name
199 wxClassInfo *info = first;
200 while (info)
201 {
202 if (info->className)
203 classTable.Put(info->className, (wxObject *)info);
204 info = info->next;
205 }
206
207 // Set base pointers for each wxClassInfo
208 info = first;
209 while (info)
210 {
211 if (info->GetBaseClassName1())
212 info->baseInfo1 = (wxClassInfo *)classTable.Get(info->GetBaseClassName1());
213 if (info->GetBaseClassName2())
214 info->baseInfo2 = (wxClassInfo *)classTable.Get(info->GetBaseClassName2());
215 info = info->next;
216 }
217 first = NULL;
218 }
219
220 wxObject *wxCreateDynamicObject(char *name)
221 {
222 wxClassInfo *info;
223
224 info = (wxClassInfo *)wxClassInfo::classTable.Get(name);
225 if (!info)
226 return (wxObject *)NULL;
227
228 return info->CreateObject();
229 }
230
231 #ifdef USE_SERIAL
232
233 #include "wx/serbase.h"
234 #include "wx/dynlib.h"
235 #include "wx/msgdlg.h"
236
237 wxObject* wxCreateStoredObject( wxInputStream &stream )
238 {
239 wxObjectInputStream obj_s(stream);
240 return obj_s.LoadObject();
241 };
242
243 void wxObject::StoreObject( wxObjectOutputStream& stream )
244 {
245 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
246 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
247
248 if (!lib) {
249 wxMessageBox("Can't load wxSerial dynamic library.", "Alert !");
250 return;
251 }
252 if (!m_serialObj) {
253 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
254
255 if (!m_serialObj) {
256 wxString message;
257
258 message.Printf("Can't find the serialization object (%s) for the object %s",
259 WXSTRINGCAST obj_name,
260 WXSTRINGCAST GetClassInfo()->GetClassName());
261 wxMessageBox(message, "Alert !");
262 return;
263 }
264 m_serialObj->SetObject(this);
265 }
266
267 m_serialObj->StoreObject(stream);
268 }
269
270 void wxObject::LoadObject( wxObjectInputStream& stream )
271 {
272 wxString obj_name = wxString(GetClassInfo()->GetClassName()) + "_Serialize";
273 wxLibrary *lib = wxTheLibraries.LoadLibrary("wxserial");
274
275 if (!m_serialObj) {
276 m_serialObj = (WXSERIAL(wxObject) *)lib->CreateObject( obj_name );
277
278 if (!m_serialObj) {
279 wxString message;
280
281 message.Printf("Can't find the serialization object (%s) for the object %s",
282 WXSTRINGCAST obj_name,
283 WXSTRINGCAST GetClassInfo()->GetClassName());
284 wxMessageBox(message, "Alert !");
285 return;
286 }
287 m_serialObj->SetObject(this);
288 }
289
290 m_serialObj->LoadObject(stream);
291 }
292
293 #endif
294
295 /*
296 * wxObject: cloning of objects
297 */
298
299 void wxObject::Ref(const wxObject& clone)
300 {
301 // delete reference to old data
302 UnRef();
303 // reference new data
304 if (clone.m_refData) {
305 m_refData = clone.m_refData;
306 ++(m_refData->m_count);
307 }
308 }
309
310 void wxObject::UnRef(void)
311 {
312 if (m_refData) {
313 assert(m_refData->m_count > 0);
314 --(m_refData->m_count);
315 if (m_refData->m_count == 0)
316 delete m_refData;
317 }
318 m_refData = (wxObjectRefData *) NULL;
319 }
320
321 /*
322 * wxObjectData
323 */
324
325 wxObjectRefData::wxObjectRefData(void) : m_count(1)
326 {
327 }
328
329 wxObjectRefData::~wxObjectRefData(void)
330 {
331 }
332