1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/object.cpp 
   3 // Purpose:     wxObject implementation 
   4 // Author:      Julian Smart 
   5 // Modified by: Ron Lee 
   8 // Copyright:   (c) 1998 Julian Smart 
   9 //              (c) 2001 Ron Lee <ron@debian.org> 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  14 #pragma implementation "object.h" 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  26     #include "wx/object.h" 
  31 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
  32 #include "wx/memory.h" 
  35 #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT 
  37     #include "wx/ioswrap.h" 
  39     #if defined(__VISAGECPP__) 
  40         #define DEBUG_PRINTF(NAME) { static int raz=0; \ 
  41             printf( #NAME " %i\n",raz); fflush(stdout); raz++; } 
  43         #define DEBUG_PRINTF(NAME) 
  45 #endif // __WXDEBUG__ || wxUSE_DEBUG_CONTEXT 
  47 // we must disable optimizations for VC.NET because otherwise its too eager 
  48 // linker discards wxClassInfo objects in release build thus breaking many, 
  50 #if defined __VISUALC__ && __VISUALC__ >= 1300 
  51     #pragma optimize("", off) 
  54 #if wxUSE_EXTENDED_RTTI 
  55 const wxClassInfo
* wxObject::sm_classParentswxObject
[] = { NULL 
} ; 
  56  wxObject
* wxVariantToObjectConverterwxObject ( wxxVariant 
&data 
) 
  57 { return data
.Get
<wxObject
*>() ; } 
  58  wxObject
* wxVariantOfPtrToObjectConverterwxObject ( wxxVariant 
&data 
) 
  59 { return &data
.Get
<wxObject
>() ; } 
  60  wxxVariant 
wxObjectToVariantConverterwxObject ( wxObject 
*data 
) 
  61  { return wxxVariant( dynamic_cast<wxObject
*> (data
)  ) ; } 
  62  wxClassInfo 
wxObject::sm_classwxObject(sm_classParentswxObject 
, wxT("") , wxT("wxObject"), 
  63             (int) sizeof(wxObject
),                              \
 
  64             (wxObjectConstructorFn
) 0   , 
  65                         (wxPropertyInfo
*) NULL
,(wxHandlerInfo
*) NULL
,0 , 0 , 
  66                         0 , wxVariantOfPtrToObjectConverterwxObject 
, wxVariantToObjectConverterwxObject 
, wxObjectToVariantConverterwxObject
); 
  67  template<> void wxStringReadValue(const wxString 
& , wxObject 
* & ){assert(0) ;} 
  68  template<> void wxStringWriteValue(wxString 
& , wxObject
* const & ){assert(0) ;} 
  69  template<> void wxStringReadValue(const wxString 
& , wxObject 
& ){assert(0) ;} 
  70  template<> void wxStringWriteValue(wxString 
& , wxObject 
const & ){assert(0) ;} 
  71  template<> const wxTypeInfo
* wxGetTypeInfo( wxObject 
** ) 
  72  { static wxClassTypeInfo 
s_typeInfo(wxT_OBJECT_PTR 
, &wxObject::sm_classwxObject
) ; return &s_typeInfo 
; } 
  73  template<> const wxTypeInfo
* wxGetTypeInfo( wxObject 
* ) 
  74  { static wxClassTypeInfo 
s_typeInfo(wxT_OBJECT 
, &wxObject::sm_classwxObject
) ; return &s_typeInfo 
; } 
  76 wxClassInfo 
wxObject::sm_classwxObject( wxT("wxObject"), 0, 0, 
  77                                         (int) sizeof(wxObject
), 
  78                                         (wxObjectConstructorFn
) 0 ); 
  81 // restore optimizations 
  82 #if defined __VISUALC__ && __VISUALC__ >= 1300 
  83     #pragma optimize("", on) 
  86 wxClassInfo
* wxClassInfo::sm_first 
= NULL
; 
  87 wxHashTable
* wxClassInfo::sm_classTable 
= NULL
; 
  89 // These are here so we can avoid 'always true/false' warnings 
  90 // by referring to these instead of TRUE/FALSE 
  91 const bool wxTrue 
= TRUE
; 
  92 const bool wxFalse 
= FALSE
; 
  94 // Is this object a kind of (a subclass of) 'info'? 
  95 // E.g. is wxWindow a kind of wxObject? 
  96 // Go from this class to superclass, taking into account 
  97 // two possible base classes. 
  98 bool wxObject::IsKindOf(wxClassInfo 
*info
) const 
 100     wxClassInfo 
*thisInfo 
= GetClassInfo(); 
 101     return (thisInfo
) ? thisInfo
->IsKindOf(info
) : FALSE 
; 
 104 #if wxUSE_STD_IOSTREAM && (defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT) 
 105 void wxObject::Dump(wxSTD ostream
& str
) 
 107     if (GetClassInfo() && GetClassInfo()->GetClassName()) 
 108         str 
<< GetClassInfo()->GetClassName(); 
 110         str 
<< _T("unknown object class"); 
 115 #if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING && defined( new ) 
 120 #ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT 
 121 void *wxObject::operator new ( size_t size
, const wxChar 
*fileName
, int lineNum 
) 
 123     return wxDebugAlloc(size
, (wxChar
*) fileName
, lineNum
, TRUE
); 
 127 #ifdef _WX_WANT_DELETE_VOID 
 128 void wxObject::operator delete ( void *buf 
) 
 134 #ifdef _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET 
 135 void wxObject::operator delete ( void *buf
, const char *_fname
, size_t _line 
) 
 141 #ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT 
 142 void wxObject::operator delete ( void *buf
, const wxChar 
*WXUNUSED(fileName
), int WXUNUSED(lineNum
) ) 
 148 #ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT 
 149 void *wxObject::operator new[] ( size_t size
, const wxChar
* fileName
, int lineNum 
) 
 151     return wxDebugAlloc(size
, (wxChar
*) fileName
, lineNum
, TRUE
, TRUE
); 
 155 #ifdef _WX_WANT_ARRAY_DELETE_VOID 
 156 void wxObject::operator delete[] ( void *buf 
) 
 158     wxDebugFree(buf
, TRUE
); 
 162 #ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT 
 163 void wxObject::operator delete[] (void * buf
, const wxChar
*  WXUNUSED(fileName
), int WXUNUSED(lineNum
) ) 
 165     wxDebugFree(buf
, TRUE
); 
 170 // ---------------------------------------------------------------------------- 
 172 // ---------------------------------------------------------------------------- 
 174 wxClassInfo::~wxClassInfo() 
 176     // remove this object from the linked list of all class infos: if we don't 
 177     // do it, loading/unloading a DLL containing static wxClassInfo objects is 
 179     if ( this == sm_first 
) 
 185         wxClassInfo 
*info 
= sm_first
; 
 188             if ( info
->m_next 
== this ) 
 190                 info
->m_next 
= m_next
; 
 200 wxClassInfo 
*wxClassInfo::FindClass(const wxChar 
*className
) 
 204         return (wxClassInfo 
*)wxClassInfo::sm_classTable
->Get(className
); 
 208         for ( wxClassInfo 
*info 
= sm_first
; info 
; info 
= info
->m_next 
) 
 210             if ( wxStrcmp(info
->GetClassName(), className
) == 0 ) 
 218 // Set pointers to base class(es) to speed up IsKindOf 
 219 void wxClassInfo::InitializeClasses() 
 221     // using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you 
 222     // link any object module twice mistakenly) will break this function 
 223     // because it will enter an infinite loop and eventually die with "out of 
 224     // memory" - as this is quite hard to detect if you're unaware of this, 
 225     // try to do some checks here 
 228     static const size_t nMaxClasses 
= 10000;    // more than we'll ever have 
 232     // Do this initialization only once, because classes are added 
 234     if ( sm_classTable 
== NULL 
) 
 236         sm_classTable 
= new wxHashTable(wxKEY_STRING
); 
 238         // Index all class infos by their class name: 
 240         for(info 
= sm_first
; info
; info 
= info
->m_next
) 
 242             if (info
->m_className
) 
 244                 wxASSERT_MSG( ++nClass 
< nMaxClasses
, 
 245                               _T("an infinite loop detected - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be by linking some object module(s) twice)?") ); 
 246                 sm_classTable
->Put(info
->m_className
, (wxObject 
*)info
); 
 252 void wxClassInfo::CleanUpClasses() 
 254     delete wxClassInfo::sm_classTable
; 
 255     wxClassInfo::sm_classTable 
= NULL
; 
 258 void wxClassInfo::Register() 
 262         sm_classTable
->Put(m_className
, (wxObject 
*)this); 
 266 void wxClassInfo::Unregister() 
 270         sm_classTable
->Delete(m_className
); 
 274 wxObject 
*wxCreateDynamicObject(const wxChar 
*name
) 
 276 #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT 
 277     DEBUG_PRINTF(wxObject 
*wxCreateDynamicObject
) 
 280     if ( wxClassInfo::sm_classTable 
) 
 282         wxClassInfo 
*info 
= (wxClassInfo 
*)wxClassInfo::sm_classTable
->Get(name
); 
 283         return info 
? info
->CreateObject() : NULL
; 
 285     else // no sm_classTable yet 
 287         for ( wxClassInfo 
*info 
= wxClassInfo::sm_first
; 
 289               info 
= info
->m_next 
) 
 291             if (info
->m_className 
&& wxStrcmp(info
->m_className
, name
) == 0) 
 292                 return info
->CreateObject(); 
 300 // ---------------------------------------------------------------------------- 
 302 // ---------------------------------------------------------------------------- 
 304 // Initialize ref data from another object (needed for copy constructor and 
 305 // assignment operator) 
 306 void wxObject::InitFrom(const wxObject
& other
) 
 308     m_refData 
= other
.m_refData
; 
 310         m_refData
->m_count
++; 
 313 void wxObject::Ref(const wxObject
& clone
) 
 315 #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT 
 316     DEBUG_PRINTF(wxObject::Ref
) 
 319     // nothing to be done 
 320     if (m_refData 
== clone
.m_refData
) 
 323     // delete reference to old data 
 326     // reference new data 
 327     if ( clone
.m_refData 
) 
 329         m_refData 
= clone
.m_refData
; 
 330         ++(m_refData
->m_count
); 
 334 void wxObject::UnRef() 
 338         wxASSERT_MSG( m_refData
->m_count 
> 0, _T("invalid ref data count") ); 
 340         if ( !--m_refData
->m_count 
) 
 346 void wxObject::AllocExclusive() 
 350         m_refData 
= CreateRefData(); 
 352     else if ( m_refData
->GetRefCount() > 1 ) 
 354         // note that ref is not going to be destroyed in this case 
 355         const wxObjectRefData
* ref 
= m_refData
; 
 358         // ... so we can still access it 
 359         m_refData 
= CloneRefData(ref
); 
 361     //else: ref count is 1, we are exclusive owners of m_refData anyhow 
 363     wxASSERT_MSG( m_refData 
&& m_refData
->GetRefCount() == 1, 
 364                   _T("wxObject::AllocExclusive() failed.") ); 
 367 wxObjectRefData 
*wxObject::CreateRefData() const 
 369     // if you use AllocExclusive() you must override this method 
 370     wxFAIL_MSG( _T("CreateRefData() must be overridden if called!") ); 
 376 wxObject::CloneRefData(const wxObjectRefData 
* WXUNUSED(data
)) const 
 378     // if you use AllocExclusive() you must override this method 
 379     wxFAIL_MSG( _T("CloneRefData() must be overridden if called!") ); 
 384 // ---------------------------------------------------------------------------- 
 386 // ---------------------------------------------------------------------------- 
 388 #if defined(__DARWIN__) && defined(WXMAKINGDLL) 
 391     void __initialize_Cplusplus(void); 
 392     void wxWindowsDylibInit(void); 
 395 // Dynamic shared library (dylib) initialization routine 
 396 //   required to initialize static C++ objects bacause of lazy dynamic linking 
 397 //   http://developer.apple.com/techpubs/macosx/Essentials/ 
 398 //          SystemOverview/Frameworks/Dynamic_Shared_Libraries.html 
 400 void wxWindowsDylibInit() 
 402     // The function __initialize_Cplusplus() must be called from the shared 
 403     // library initialization routine to cause the static C++ objects in 
 404     // the library to be initialized (reference number 2441683). 
 406     // This only seems to be necessary if the library initialization routine 
 407     // needs to use the static C++ objects 
 408     __initialize_Cplusplus();