]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/objstrm.cpp
We use native paths now in wxWindows. On the Mac, too.
[wxWidgets.git] / src / common / objstrm.cpp
index 1d2b01d01a30b9b74eb2d52f6cf0bc1507505129..e0156b200dd51ba569bc88bb5c04f5b88b5621e8 100644 (file)
@@ -8,10 +8,20 @@
 // Copyright:   (c) 1998 Guilhem Lavaux
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
+
 #ifdef __GNUG__
-#pragma implementation "objstrm.h"
+    #pragma implementation "objstrm.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+  #pragma hdrstop
 #endif
 
+#if wxUSE_SERIAL && wxUSE_STREAMS
+
 #include "wx/object.h"
 #include "wx/objstrm.h"
 #include "wx/datstrm.h"
@@ -19,6 +29,9 @@
 #define WXOBJ_BEGIN "OBEGIN"
 #define WXOBJ_BEG_LEN 6
 
+#define TAG_EMPTY_OBJECT "NULL"
+#define TAG_DUPLICATE_OBJECT "DUPLIC"
+
 // ----------------------------------------------------------------------------
 // wxObjectOutputStream
 // ----------------------------------------------------------------------------
@@ -33,7 +46,7 @@ wxString wxObjectOutputStream::GetObjectName(wxObject *obj)
 {
   wxString name;
 
-  name.Printf("%x", (unsigned long)obj);
+  name.Printf(wxT("%x"), (unsigned long)obj);
   return name;
 }
 
@@ -42,13 +55,31 @@ void wxObjectOutputStream::WriteObjectDef(wxObjectStreamInfo& info)
   wxDataOutputStream data_s(*this); 
 
   Write(WXOBJ_BEGIN, WXOBJ_BEG_LEN);
-  data_s.WriteString(info.object->GetClassInfo()->GetClassName());
+
+  if (info.duplicate) {
+    data_s.WriteString(TAG_DUPLICATE_OBJECT);
+    data_s.WriteString(GetObjectName(info.object));
+    wxPrintf(wxT("info.object (dup %s)\n"), info.object->GetClassInfo()->GetClassName());
+    return;
+  }
+
+  if (info.object) {
+    data_s.WriteString(info.object->GetClassInfo()->GetClassName());
+    wxPrintf(wxT("info.object (%s)\n"), info.object->GetClassInfo()->GetClassName());
+  } else {
+    data_s.WriteString(TAG_EMPTY_OBJECT);
+    wxPrintf(wxT("info.object (NULL)\n"));
+    return;
+  }
+
   data_s.WriteString(GetObjectName(info.object));
+
   // I assume an object will not have millions of children
-  data_s.Write8(info.children.Number());
+  // Hmmm ... it could have (for example wxGrid)
+  data_s.Write32(info.children.Number());
 }
 
-void wxObjectOutputStream::AddChildren(wxObject *obj)
+void wxObjectOutputStream::AddChild(wxObject *obj)
 {
   wxObjectStreamInfo *info;
 
@@ -56,9 +87,19 @@ void wxObjectOutputStream::AddChildren(wxObject *obj)
     return;
 
   info = new wxObjectStreamInfo;
+
+  if (m_saved_objs.Member(obj) != NULL) {
+    info->duplicate = TRUE;
+  } else {
+    info->duplicate = FALSE;
+    m_saved_objs.Append(obj);
+  }
+  if (!obj)
+    info->duplicate = FALSE;
+
   info->n_children = 0;
   info->object = obj;
-  info->parent = m_current_info->object; // Not useful here.
+  info->parent = m_current_info; // Not useful here.
   m_current_info->n_children++;
   m_current_info->children.Append(info);
 }
@@ -69,7 +110,8 @@ void wxObjectOutputStream::ProcessObjectDef(wxObjectStreamInfo *info)
 
   m_current_info = info;
   // First stage: get children of obj
-  info->object->StoreObject(*this);
+  if (info->object && !info->duplicate)
+    info->object->StoreObject(*this);
 
   // Prepare and write the sub-entry about the child obj.
   WriteObjectDef(*info);
@@ -88,7 +130,8 @@ void wxObjectOutputStream::ProcessObjectData(wxObjectStreamInfo *info)
 
   m_current_info = info;
 
-  info->object->StoreObject(*this);
+  if (info->object && !info->duplicate)
+    info->object->StoreObject(*this);
 
   while (node) {
     ProcessObjectData((wxObjectStreamInfo *)node->Data());
@@ -109,12 +152,14 @@ bool wxObjectOutputStream::SaveObject(wxObject& obj)
   m_stage = 0;
   info.object = &obj;
   info.n_children = 0;
+  info.duplicate = FALSE;
   ProcessObjectDef(&info);
 
   m_stage = 1;
   ProcessObjectData(&info);
 
   info.children.Clear();
+  m_saved_objs.Clear();
 
   m_saving = FALSE;
 
@@ -128,6 +173,7 @@ bool wxObjectOutputStream::SaveObject(wxObject& obj)
 wxObjectInputStream::wxObjectInputStream(wxInputStream& s)
   : wxFilterInputStream(s)
 {
+  m_secondcall = FALSE;
 }
 
 wxObject *wxObjectInputStream::SolveName(const wxString& name) const
@@ -142,28 +188,74 @@ wxObject *wxObjectInputStream::SolveName(const wxString& name) const
 
     node = node->Next();
   }
-  return NULL;
+  return (wxObject *) NULL;
+}
+
+wxObject *wxObjectInputStream::GetParent() const
+{
+  if (!m_current_info->parent)
+    return (wxObject *) NULL;
+
+  return m_current_info->parent->object;
+}
+
+wxObject *wxObjectInputStream::GetChild()
+{
+  wxObject *obj = GetChild(0);
+
+  m_current_info->children_removed++;
+
+  return obj;
 }
 
 wxObject *wxObjectInputStream::GetChild(int no) const
 {
-  return m_current_info->children.Nth(no);
+  wxNode *node;
+  wxObjectStreamInfo *info;
+
+  if (m_current_info->children_removed >= m_current_info->n_children)
+    return (wxObject *) NULL;
+
+  node = m_current_info->children.Nth(m_current_info->children_removed+no);
+
+  if (!node)
+    return (wxObject *) NULL;
+
+  info = (wxObjectStreamInfo *)node->Data();
+
+  return info->object;
+}
+
+void wxObjectInputStream::RemoveChildren(int nb)
+{
+  m_current_info->children_removed += nb;
 }
 
 bool wxObjectInputStream::ReadObjectDef(wxObjectStreamInfo *info)
 {
   wxDataInputStream data_s(*this);
   char sig[WXOBJ_BEG_LEN+1];
+  wxString class_name;
 
   Read(sig, WXOBJ_BEG_LEN);
   sig[WXOBJ_BEG_LEN] = 0;
   if (wxString(sig) != WXOBJ_BEGIN)
     return FALSE;
-  info->object = wxCreateDynamicObject((char *)data_s.ReadString());
-  info->object_name = data_s.ReadString();
-  info->n_children = data_s.Read8();
-  info->children = wxList();
 
+  class_name = data_s.ReadString();
+  info->children_removed = 0;
+  info->n_children = 0;
+
+  if (class_name == TAG_EMPTY_OBJECT)
+    info->object = (wxObject *) NULL;
+  else if (class_name == TAG_DUPLICATE_OBJECT) {
+    info->object_name = data_s.ReadString();
+    info->object = SolveName(info->object_name);
+  } else {
+    info->object_name = data_s.ReadString();
+    info->object = wxCreateDynamicObject( WXSTRINGCAST class_name);
+    info->n_children = data_s.Read32();
+  }
   return TRUE;
 }
 
@@ -179,12 +271,12 @@ wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *pa
   m_solver.Append(info);
 
   if (!ReadObjectDef(info))
-    return NULL;
+    return (wxObjectStreamInfo *) NULL;
 
   for (c=0;c<info->n_children;c++) {
     c_info = ProcessObjectDef(info);
     if (!c_info)
-      return NULL;
+      return (wxObjectStreamInfo *) NULL;
     info->children.Append(c_info);
   }
 
@@ -194,16 +286,23 @@ wxObjectStreamInfo *wxObjectInputStream::ProcessObjectDef(wxObjectStreamInfo *pa
 void wxObjectInputStream::ProcessObjectData(wxObjectStreamInfo *info)
 {
   wxNode *node = info->children.First();
-  wxObjectStreamInfo *c_info;
 
   m_current_info = info;
 
-  info->object->LoadObject(*this);
+  if (info->object)
+    info->object->LoadObject(*this);
   while (node) {
-    c_info = (wxObjectStreamInfo *)node->Data();
-    c_info->object->LoadObject(*this);
+    ProcessObjectData((wxObjectStreamInfo *)node->Data());
     node = node->Next();
   }
+
+  m_current_info = info;
+
+  if (info->recall) {
+    m_secondcall = TRUE;
+    info->object->LoadObject(*this);
+    m_secondcall = FALSE;
+  }
 }
 
 wxObject *wxObjectInputStream::LoadObject()
@@ -211,9 +310,9 @@ wxObject *wxObjectInputStream::LoadObject()
   wxObjectStreamInfo *info;
   wxObject *object;
 
-  info = ProcessObjectDef(NULL);
+  info = ProcessObjectDef((wxObjectStreamInfo *) NULL);
   if (!info)
-    return NULL;
+    return (wxObject *) NULL;
   ProcessObjectData(info);
 
   object = info->object;
@@ -222,3 +321,6 @@ wxObject *wxObjectInputStream::LoadObject()
 
   return object;
 }
+
+#endif // wxUSE_SERIAL && wxUSE_STREAMS
+