home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / object.cpp < prev    next >
C/C++ Source or Header  |  2002-08-16  |  11KB  |  387 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        src/common/object.cpp
  3. // Purpose:     wxObject implementation
  4. // Author:      Julian Smart
  5. // Modified by: Ron Lee
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: object.cpp,v 1.66 2002/08/13 22:37:41 VZ Exp $
  8. // Copyright:   (c) 1998 Julian Smart and Markus Holzem
  9. //              (c) 2001 Ron Lee <ron@debian.org>
  10. // Licence:     wxWindows license
  11. /////////////////////////////////////////////////////////////////////////////
  12.  
  13. #ifdef __GNUG__
  14. #pragma implementation "object.h"
  15. #endif
  16.  
  17. // For compilers that support precompilation, includes "wx.h".
  18. #include "wx/wxprec.h"
  19.  
  20. #ifdef __BORLANDC__
  21. #pragma hdrstop
  22. #endif
  23.  
  24. #ifndef WX_PRECOMP
  25. #include "wx/hash.h"
  26. #endif
  27.  
  28. #include <string.h>
  29.  
  30. #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
  31. #include "wx/memory.h"
  32. #endif
  33.  
  34. #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
  35.     // for wxObject::Dump
  36.     #include "wx/ioswrap.h"
  37.  
  38.     #if defined(__VISAGECPP__)
  39.         #define DEBUG_PRINTF(NAME) { static int raz=0; \
  40.             printf( #NAME " %i\n",raz); fflush(stdout); raz++; }
  41.     #else
  42.         #define DEBUG_PRINTF(NAME)
  43.     #endif
  44. #endif // __WXDEBUG__ || wxUSE_DEBUG_CONTEXT
  45.  
  46.  
  47. wxClassInfo wxObject::sm_classwxObject( wxT("wxObject"), 0, 0,
  48.                                         (int) sizeof(wxObject),
  49.                                         (wxObjectConstructorFn) 0 );
  50.  
  51. wxClassInfo* wxClassInfo::sm_first = NULL;
  52. wxHashTable* wxClassInfo::sm_classTable = NULL;
  53.  
  54. // These are here so we can avoid 'always true/false' warnings
  55. // by referring to these instead of TRUE/FALSE
  56. const bool wxTrue = TRUE;
  57. const bool wxFalse = FALSE;
  58.  
  59. // Is this object a kind of (a subclass of) 'info'?
  60. // E.g. is wxWindow a kind of wxObject?
  61. // Go from this class to superclass, taking into account
  62. // two possible base classes.
  63. bool wxObject::IsKindOf(wxClassInfo *info) const
  64. {
  65.     wxClassInfo *thisInfo = GetClassInfo();
  66.     return (thisInfo) ? thisInfo->IsKindOf(info) : FALSE ;
  67. }
  68.  
  69. #if wxUSE_STD_IOSTREAM && (defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT)
  70. void wxObject::Dump(wxSTD ostream& str)
  71. {
  72.     if (GetClassInfo() && GetClassInfo()->GetClassName())
  73.         str << GetClassInfo()->GetClassName();
  74.     else
  75.         str << _T("unknown object class");
  76. }
  77. #endif
  78.  
  79.  
  80. #if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING && defined( new )
  81.     #undef new
  82. #endif
  83.  
  84.  
  85. #ifdef _WX_WANT_NEW_SIZET_WXCHAR_INT
  86. void *wxObject::operator new ( size_t size, const wxChar *fileName, int lineNum )
  87. {
  88.     return wxDebugAlloc(size, (wxChar*) fileName, lineNum, TRUE);
  89. }
  90. #endif
  91.  
  92. #ifdef _WX_WANT_DELETE_VOID
  93. void wxObject::operator delete ( void *buf )
  94. {
  95.     wxDebugFree(buf);
  96. }
  97. #endif
  98.  
  99. #ifdef _WX_WANT_DELETE_VOID_CONSTCHAR_SIZET
  100. void wxObject::operator delete ( void *buf, const char *_fname, size_t _line )
  101. {
  102.     wxDebugFree(buf);
  103. }
  104. #endif
  105.  
  106. #ifdef _WX_WANT_DELETE_VOID_WXCHAR_INT
  107. void wxObject::operator delete ( void *buf, const wxChar *WXUNUSED(fileName), int WXUNUSED(lineNum) )
  108. {
  109.      wxDebugFree(buf);
  110. }
  111. #endif
  112.  
  113. #ifdef _WX_WANT_ARRAY_NEW_SIZET_WXCHAR_INT
  114. void *wxObject::operator new[] ( size_t size, const wxChar* fileName, int lineNum )
  115. {
  116.     return wxDebugAlloc(size, (wxChar*) fileName, lineNum, TRUE, TRUE);
  117. }
  118. #endif
  119.  
  120. #ifdef _WX_WANT_ARRAY_DELETE_VOID
  121. void wxObject::operator delete[] ( void *buf )
  122. {
  123.     wxDebugFree(buf, TRUE);
  124. }
  125. #endif
  126.  
  127. #ifdef _WX_WANT_ARRAY_DELETE_VOID_WXCHAR_INT
  128. void wxObject::operator delete[] (void * buf, const wxChar*  WXUNUSED(fileName), int WXUNUSED(lineNum) )
  129. {
  130.     wxDebugFree(buf, TRUE);
  131. }
  132. #endif
  133.  
  134.  
  135. // ----------------------------------------------------------------------------
  136. // wxClassInfo
  137. // ----------------------------------------------------------------------------
  138.  
  139. wxClassInfo::~wxClassInfo()
  140. {
  141.     // remove this object from the linked list of all class infos: if we don't
  142.     // do it, loading/unloading a DLL containing static wxClassInfo objects is
  143.     // not going to work
  144.     if ( this == sm_first )
  145.     {
  146.         sm_first = m_next;
  147.     }
  148.     else
  149.     {
  150.         wxClassInfo *info = sm_first;
  151.         while (info)
  152.         {
  153.             if ( info->m_next == this )
  154.             {
  155.                 info->m_next = m_next;
  156.                 break;
  157.             }
  158.  
  159.             info = info->m_next;
  160.         }
  161.     }
  162. }
  163.  
  164. wxClassInfo *wxClassInfo::FindClass(const wxChar *className)
  165. {
  166.     if ( sm_classTable )
  167.     {
  168.         return (wxClassInfo *)wxClassInfo::sm_classTable->Get(className);
  169.     }
  170.     else
  171.     {
  172.         for ( wxClassInfo *info = sm_first; info ; info = info->m_next )
  173.         {
  174.             if ( wxStrcmp(info->GetClassName(), className) == 0 )
  175.                 return info;
  176.         }
  177.  
  178.         return NULL;
  179.     }
  180. }
  181.  
  182. // a tiny InitializeClasses() helper
  183. /* static */
  184. inline wxClassInfo *wxClassInfo::GetBaseByName(const wxChar *name)
  185. {
  186.     if ( !name )
  187.         return NULL;
  188.  
  189.     wxClassInfo *classInfo = (wxClassInfo *)sm_classTable->Get(name);
  190.  
  191.     // this must be fixed, other things risk work wrongly later if you get this
  192.     wxASSERT_MSG( classInfo,
  193.                   wxString::Format
  194.                   (
  195.                     _T("base class '%s' is unknown to wxWindows RTTI"),
  196.                     name
  197.                   ) );
  198.  
  199.     return classInfo;
  200. }
  201.  
  202. // Set pointers to base class(es) to speed up IsKindOf
  203. void wxClassInfo::InitializeClasses()
  204. {
  205.     // using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you
  206.     // link any object module twice mistakenly) will break this function
  207.     // because it will enter an infinite loop and eventually die with "out of
  208.     // memory" - as this is quite hard to detect if you're unaware of this,
  209.     // try to do some checks here
  210.  
  211. #ifdef __WXDEBUG__
  212.     static const size_t nMaxClasses = 10000;    // more than we'll ever have
  213.     size_t nClass = 0;
  214. #endif
  215.  
  216.     sm_classTable = new wxHashTable(wxKEY_STRING);
  217.  
  218.         // Index all class infos by their class name
  219.  
  220.     wxClassInfo *info;
  221.     for(info = sm_first; info; info = info->m_next)
  222.     {
  223.         if (info->m_className)
  224.         {
  225.             wxASSERT_MSG( ++nClass < nMaxClasses,
  226.                           _T("an infinite loop detected - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be by linking some object module(s) twice)?") );
  227.             sm_classTable->Put(info->m_className, (wxObject *)info);
  228.         }
  229.     }
  230.  
  231.         // Set base pointers for each wxClassInfo
  232.  
  233.     for(info = sm_first; info; info = info->m_next)
  234.     {
  235.         info->m_baseInfo1 = GetBaseByName(info->GetBaseClassName1());
  236.         info->m_baseInfo2 = GetBaseByName(info->GetBaseClassName2());
  237.     }
  238. }
  239.  
  240. void wxClassInfo::CleanUpClasses()
  241. {
  242.     delete wxClassInfo::sm_classTable;
  243.     wxClassInfo::sm_classTable = NULL;
  244. }
  245.  
  246.  
  247. wxObject *wxCreateDynamicObject(const wxChar *name)
  248. {
  249. #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
  250.     DEBUG_PRINTF(wxObject *wxCreateDynamicObject)
  251. #endif
  252.  
  253.     if ( wxClassInfo::sm_classTable )
  254.     {
  255.         wxClassInfo *info = (wxClassInfo *)wxClassInfo::sm_classTable->Get(name);
  256.         return info ? info->CreateObject() : NULL;
  257.     }
  258.     else // no sm_classTable yet
  259.     {
  260.         for ( wxClassInfo *info = wxClassInfo::sm_first;
  261.               info;
  262.               info = info->m_next )
  263.         {
  264.             if (info->m_className && wxStrcmp(info->m_className, name) == 0)
  265.                 return info->CreateObject();
  266.         }
  267.  
  268.         return NULL;
  269.     }
  270. }
  271.  
  272.  
  273. // ----------------------------------------------------------------------------
  274. // wxObject
  275. // ----------------------------------------------------------------------------
  276.  
  277. // Initialize ref data from another object (needed for copy constructor and
  278. // assignment operator)
  279. void wxObject::InitFrom(const wxObject& other)
  280. {
  281.     m_refData = other.m_refData;
  282.     if ( m_refData )
  283.         m_refData->m_count++;
  284. }
  285.  
  286. void wxObject::Ref(const wxObject& clone)
  287. {
  288. #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT
  289.     DEBUG_PRINTF(wxObject::Ref)
  290. #endif
  291.  
  292.     // nothing to be done
  293.     if (m_refData == clone.m_refData)
  294.         return;
  295.  
  296.     // delete reference to old data
  297.     UnRef();
  298.  
  299.     // reference new data
  300.     if ( clone.m_refData )
  301.     {
  302.         m_refData = clone.m_refData;
  303.         ++(m_refData->m_count);
  304.     }
  305. }
  306.  
  307. void wxObject::UnRef()
  308. {
  309.     if ( m_refData )
  310.     {
  311.         wxASSERT_MSG( m_refData->m_count > 0, _T("invalid ref data count") );
  312.  
  313.         if ( !--m_refData->m_count )
  314.             delete m_refData;
  315.         m_refData = NULL;
  316.     }
  317. }
  318.  
  319. void wxObject::AllocExclusive()
  320. {
  321.     if ( !m_refData )
  322.     {
  323.         m_refData = CreateRefData();
  324.     }
  325.     else if ( m_refData->GetRefCount() > 1 )
  326.     {
  327.         // note that ref is not going to be destroyed in this case
  328.         const wxObjectRefData* ref = m_refData;
  329.         UnRef();
  330.  
  331.         // ... so we can still access it
  332.         m_refData = CloneRefData(ref);
  333.     }
  334.     //else: ref count is 1, we are exclusive owners of m_refData anyhow
  335.  
  336.     wxASSERT_MSG( m_refData && m_refData->GetRefCount() == 1,
  337.                   _T("wxObject::AllocExclusive() failed.") );
  338. }
  339.  
  340. wxObjectRefData *wxObject::CreateRefData() const
  341. {
  342.     // if you use AllocExclusive() you must override this method
  343.     wxFAIL_MSG( _T("CreateRefData() must be overridden if called!") );
  344.  
  345.     return NULL;
  346. }
  347.  
  348. wxObjectRefData *
  349. wxObject::CloneRefData(const wxObjectRefData * WXUNUSED(data)) const
  350. {
  351.     // if you use AllocExclusive() you must override this method
  352.     wxFAIL_MSG( _T("CloneRefData() must be overridden if called!") );
  353.  
  354.     return NULL;
  355. }
  356.  
  357. // ----------------------------------------------------------------------------
  358. // misc
  359. // ----------------------------------------------------------------------------
  360.  
  361. #if defined(__DARWIN__) && defined(WXMAKINGDLL)
  362.  
  363. extern "C" {
  364.     void __initialize_Cplusplus(void);
  365.     void wxWindowsDylibInit(void);
  366. };
  367.  
  368. // Dynamic shared library (dylib) initialization routine
  369. //   required to initialize static C++ objects bacause of lazy dynamic linking
  370. //   http://developer.apple.com/techpubs/macosx/Essentials/
  371. //          SystemOverview/Frameworks/Dynamic_Shared_Libraries.html
  372.  
  373. void wxWindowsDylibInit()
  374. {
  375.     // The function __initialize_Cplusplus() must be called from the shared
  376.     // library initialization routine to cause the static C++ objects in
  377.     // the library to be initialized (reference number 2441683).
  378.  
  379.     // This only seems to be necessary if the library initialization routine
  380.     // needs to use the static C++ objects
  381.     __initialize_Cplusplus();
  382. }
  383.  
  384. #endif
  385.  
  386. // vi:sts=4:sw=4:et
  387.