]> git.saurik.com Git - wxWidgets.git/blame - src/common/objstrm.cpp
Fixed bug in function Flush().
[wxWidgets.git] / src / common / objstrm.cpp
CommitLineData
6d44bf31
GL
1/////////////////////////////////////////////////////////////////////////////
2// Name: objstrm.cpp
3// Purpose: wxObjectStream classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 16/07/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Guilhem Lavaux
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11#ifdef __GNUG__
12#pragma implementation "objstrm.h"
13#endif
14
fcc6dddd
JS
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
ce4169a4 19 #pragma hdrstop
fcc6dddd
JS
20#endif
21
ce4169a4 22#if wxUSE_SERIAL && wxUSE_STREAMS
fcc6dddd 23
6d44bf31
GL
24#include "wx/object.h"
25#include "wx/objstrm.h"
26#include "wx/datstrm.h"
27
28#define WXOBJ_BEGIN "OBEGIN"
29#define WXOBJ_BEG_LEN 6
30
7a4b9130 31#define TAG_EMPTY_OBJECT "NULL"
8d43638d 32#define TAG_DUPLICATE_OBJECT "DUPLIC"
7a4b9130 33
6d44bf31
GL
34// ----------------------------------------------------------------------------
35// wxObjectOutputStream
36// ----------------------------------------------------------------------------
37
38wxObjectOutputStream::wxObjectOutputStream(wxOutputStream& s)
39 : wxFilterOutputStream(s)
40{
41 m_saving = FALSE;
42}
43
44wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
45{
46 wxString name;
47
84fff0b3 48 name.Printf(_T("%x"), (unsigned long)obj);
6d44bf31
GL
49 return name;
50}
51
52void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info)
53{
54 wxDataOutputStream data_s(*this);
55
56 Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN);
7a4b9130 57
8d43638d
GL
58 if (info.duplicate) {
59 data_s.WriteString(TAG_DUPLICATE_OBJECT);
60 data_s.WriteString(GetObjectName(info.object));
84fff0b3 61 wxPrintf(_T("info.object (dup %s)\n"), info.object->GetClassInfo()->GetClassName());
8d43638d
GL
62 return;
63 }
64
7a4b9130
GL
65 if (info.object) {
66 data_s.WriteString(info.object->GetClassInfo()->GetClassName());
84fff0b3 67 wxPrintf(_T("info.object (%s)\n"), info.object->GetClassInfo()->GetClassName());
7a4b9130
GL
68 } else {
69 data_s.WriteString(TAG_EMPTY_OBJECT);
84fff0b3 70 wxPrintf(_T("info.object (NULL)\n"));
1d44aaf8 71 return;
7a4b9130
GL
72 }
73
6d44bf31 74 data_s.WriteString(GetObjectName(info.object));
7a4b9130 75
6d44bf31 76 // I assume an object will not have millions of children
8d43638d
GL
77 // Hmmm ... it could have (for example wxGrid)
78 data_s.Write32(info.children.Number());
6d44bf31
GL
79}
80
1eac776c 81void wxObjectOutputStream::AddChild(wxObject *obj)
6d44bf31
GL
82{
83 wxObjectStreamInfo *info;
84
85 if (!FirstStage())
86 return;
87
88 info = new wxObjectStreamInfo;
8d43638d
GL
89
90 if (m_saved_objs.Member(obj) != NULL) {
91 info->duplicate = TRUE;
92 } else {
93 info->duplicate = FALSE;
94 m_saved_objs.Append(obj);
95 }
1d44aaf8
GL
96 if (!obj)
97 info->duplicate = FALSE;
98
6d44bf31
GL
99 info->n_children = 0;
100 info->object = obj;
7a4b9130 101 info->parent = m_current_info; // Not useful here.
6d44bf31
GL
102 m_current_info->n_children++;
103 m_current_info->children.Append(info);
104}
105
106void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info)
107{
108 wxNode *node;
109
110 m_current_info = info;
111 // First stage: get children of obj
8d43638d 112 if (info->object && !info->duplicate)
7a4b9130 113 info->object->StoreObject(*this);
6d44bf31
GL
114
115 // Prepare and write the sub-entry about the child obj.
116 WriteObjectDef(*info);
117
118 node = info->children.First();
119
120 while (node) {
121 ProcessObjectDef((wxObjectStreamInfo *)node->Data());
122 node = node->Next();
123 }
124}
125
126void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info)
127{
128 wxNode *node = info->children.First();
129
130 m_current_info = info;
131
8d43638d 132 if (info->object && !info->duplicate)
7a4b9130 133 info->object->StoreObject(*this);
6d44bf31
GL
134
135 while (node) {
136 ProcessObjectData((wxObjectStreamInfo *)node->Data());
137 node = node->Next();
138 }
139}
140
141bool wxObjectOutputStream::SaveObject(wxObject& obj)
142{
143 wxObjectStreamInfo info;
144
145 if (m_saving)
146 return FALSE;
147
148 m_saving = TRUE;
149
150 // First stage
151 m_stage = 0;
152 info.object = &obj;
153 info.n_children = 0;
1d44aaf8 154 info.duplicate = FALSE;
6d44bf31
GL
155 ProcessObjectDef(&info);
156
157 m_stage = 1;
158 ProcessObjectData(&info);
159
160 info.children.Clear();
8d43638d 161 m_saved_objs.Clear();
6d44bf31
GL
162
163 m_saving = FALSE;
164
165 return TRUE;
166}
167
168// ----------------------------------------------------------------------------
169// wxObjectInputStream
170// ----------------------------------------------------------------------------
171
172wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
173 : wxFilterInputStream(s)
174{
856d2e52 175 m_secondcall = FALSE;
6d44bf31
GL
176}
177
178wxObject *wxObjectInputStream::SolveName(const wxString& name) const
179{
180 wxNode *node = m_solver.First();
181 wxObjectStreamInfo *info;
182
183 while (node) {
184 info = (wxObjectStreamInfo *)node->Data();
185 if (info->object_name == name)
186 return info->object;
187
188 node = node->Next();
189 }
c67daf87 190 return (wxObject *) NULL;
6d44bf31
GL
191}
192
7a4b9130
GL
193wxObject *wxObjectInputStream::GetParent() const
194{
195 if (!m_current_info->parent)
c67daf87 196 return (wxObject *) NULL;
7a4b9130
GL
197
198 return m_current_info->parent->object;
199}
200
1d44aaf8
GL
201wxObject *wxObjectInputStream::GetChild()
202{
203 wxObject *obj = GetChild(0);
204
205 m_current_info->children_removed++;
206
207 return obj;
208}
209
6d44bf31
GL
210wxObject *wxObjectInputStream::GetChild(int no) const
211{
1d44aaf8 212 wxNode *node;
7a4b9130
GL
213 wxObjectStreamInfo *info;
214
1d44aaf8 215 if (m_current_info->children_removed >= m_current_info->n_children)
5104949d 216 return (wxObject *) NULL;
1d44aaf8
GL
217
218 node = m_current_info->children.Nth(m_current_info->children_removed+no);
219
7a4b9130 220 if (!node)
c67daf87 221 return (wxObject *) NULL;
7a4b9130
GL
222
223 info = (wxObjectStreamInfo *)node->Data();
224
225 return info->object;
226}
227
228void wxObjectInputStream::RemoveChildren(int nb)
229{
230 m_current_info->children_removed += nb;
6d44bf31
GL
231}
232
233bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
234{
235 wxDataInputStream data_s(*this);
236 char sig[WXOBJ_BEG_LEN+1];
7a4b9130 237 wxString class_name;
6d44bf31
GL
238
239 Read(sig, WXOBJ_BEG_LEN);
240 sig[WXOBJ_BEG_LEN] = 0;
241 if (wxString(sig) != WXOBJ_BEGIN)
242 return FALSE;
7a4b9130
GL
243
244 class_name = data_s.ReadString();
7a4b9130 245 info->children_removed = 0;
f4a8c29f 246 info->n_children = 0;
6d44bf31 247
8d43638d 248 if (class_name == TAG_EMPTY_OBJECT)
c67daf87 249 info->object = (wxObject *) NULL;
8d43638d 250 else if (class_name == TAG_DUPLICATE_OBJECT) {
1d44aaf8 251 info->object_name = data_s.ReadString();
8d43638d 252 info->object = SolveName(info->object_name);
8d43638d 253 } else {
1d44aaf8 254 info->object_name = data_s.ReadString();
8d43638d 255 info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
1d44aaf8 256 info->n_children = data_s.Read32();
8d43638d 257 }
6d44bf31
GL
258 return TRUE;
259}
260
261wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *parent)
262{
263 wxObjectStreamInfo *info, *c_info;
264 int c;
265
266 info = new wxObjectStreamInfo;
267 info->parent = parent;
268 info->children.DeleteContents(TRUE);
269
270 m_solver.Append(info);
271
272 if (!ReadObjectDef(info))
c67daf87 273 return (wxObjectStreamInfo *) NULL;
6d44bf31
GL
274
275 for (c=0;c<info->n_children;c++) {
276 c_info = ProcessObjectDef(info);
277 if (!c_info)
c67daf87 278 return (wxObjectStreamInfo *) NULL;
6d44bf31
GL
279 info->children.Append(c_info);
280 }
281
282 return info;
283}
284
285void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info)
286{
287 wxNode *node = info->children.First();
6d44bf31
GL
288
289 m_current_info = info;
290
7a4b9130
GL
291 if (info->object)
292 info->object->LoadObject(*this);
6d44bf31 293 while (node) {
7a4b9130 294 ProcessObjectData((wxObjectStreamInfo *)node->Data());
6d44bf31
GL
295 node = node->Next();
296 }
1d44aaf8
GL
297
298 m_current_info = info;
299
300 if (info->recall) {
301 m_secondcall = TRUE;
302 info->object->LoadObject(*this);
303 m_secondcall = FALSE;
304 }
6d44bf31
GL
305}
306
307wxObject *wxObjectInputStream::LoadObject()
308{
309 wxObjectStreamInfo *info;
310 wxObject *object;
311
c67daf87 312 info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
6d44bf31 313 if (!info)
c67daf87 314 return (wxObject *) NULL;
6d44bf31
GL
315 ProcessObjectData(info);
316
317 object = info->object;
318
319 delete info; // It's magic ! The whole tree is destroyed.
320
321 return object;
322}
fcc6dddd
JS
323
324#endif
325