ccobject.h

Go to the documentation of this file.
00001 // $Id: ccobject.h 751 2006-03-31 15:43:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 /*
00100  *  */
00101 
00102 #ifndef INC_CCOBJECT
00103 #define INC_CCOBJECT
00104 
00105 // CCObject and CCRuntimeClass are mutually dependent, so we have these forward references.
00106 class CCObject;
00107 class CCRuntimeClass;
00108 
00109 
00110 /********************************************************************************************
00111 
00112 >   class CCRuntimeClass
00113 
00114     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00115     Created:    15/7/93
00116     Purpose:    Provide run-time class information and dynamic class creation for objects
00117                 derived from CCObject.
00118                 
00119     SeeAlso:    CCObject
00120 
00121 ********************************************************************************************/
00122 
00123 
00124 class CCAPI CCRuntimeClass
00125 {
00126 public:
00127     // Text string og the class's name e.g. "CCObject"
00128     LPCTSTR m_lpszClassName;
00129     
00130     // Size of the object in bytes
00131     INT32 m_nObjectSize;
00132     
00133     // Schema number - this used in serialisation. (-1 for classes which do not support
00134     // serialisation).
00135     UINT32 m_wSchema; 
00136     
00137     // If the class supports dynamic creation, this is a pointer to the default
00138     // constructor for the class. Do not use this pointer - use CreateObject() instead.
00139     void (PASCAL* m_pfnConstruct)(void* p);
00140     
00141     // A pointer to the runtime class information object of the base class that this
00142     // class is derived from.
00143     CCRuntimeClass* m_pBaseClass;
00144 
00145     // If the class supports dynamic creation, this function will create an instance of
00146     // the required class.  e.g.  RUNTIME_CLASS(Node)->CreateObject()
00147     CCObject* CreateObject();
00148     BOOL ConstructObject(void* pThis);
00149     BOOL IsKindOf(const CCRuntimeClass* pClass) const;
00150     LPCTSTR         GetClassName() const {return m_lpszClassName;}
00151     CCRuntimeClass* GetBaseClass1() const {return m_pBaseClass;}
00152     INT32               GetSize() const {return m_nObjectSize;}
00153 
00154     // Used to maintain the global list of CCRuntimeClass structures of all classes
00155     // derived from CCObject which support dynamic classing (CC_DECLARE_DYNAMIC).
00156     // This list is built by constructors of static class members of type
00157     // CC_CLASSINIT.
00158     static CCRuntimeClass* pFirstClass; 
00159     CCRuntimeClass* m_pNextClass;       
00160 };
00161 
00162 
00163 /********************************************************************************************
00164 
00165 >   class SimpleCCObject
00166 
00167     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00168     Created:    15/7/93
00169     Purpose:    Override new and delete, so that new returns NULL when no more memory is
00170                 available, rather than throwing an exception.
00171                 
00172                 NB. ALL Camelot objects not derived from OIL class libraries should be
00173                 be derived from SimpleCCObject in some way, be it directly, or via CCObject.
00174                 This is so they don't throw exceptions if we try to create them and there is
00175                 not enough memory.
00176     SeeAlso:    -
00177 
00178 ********************************************************************************************/
00179 
00180 class CCAPI SimpleCCObject
00181 {
00182 public:
00183 
00184     // This version of new is used to dynamically create objects - it allocates
00185     // no memory, but calls the constructor to fill in object's data pointed to
00186     // by p. (See Construct and ConstructObject).
00187     // The operation of this dynamic creation is not fully understood at this time...
00188     void* operator new(size_t, void* p) { return p; }
00189 #if defined(__WXMSW__)
00190     void operator delete(void* p, void* p1) {delete p;}
00191 #elif defined(__WXMAC__)
00192 PORTNOTE("MacPort", "Memory tracking is disabled on the Mac")
00193 //  void operator delete(void* p, void* p1) {delete p;}
00194 #endif
00195     
00196     // 'Standard' new/delete functions.
00197     void* operator new(size_t nSize);
00198     void operator delete(void* p);
00199 
00200     void* operator new(size_t nSize, LPCSTR lpszFileName, INT32 nLine);
00201 #if defined(__WXMSW__)
00202     void operator delete(void* p, LPCSTR lpszFileName, INT32 nLine) {delete p;}
00203 #elif defined(__WXMAC__)
00204 PORTNOTE("MacPort", "Memory tracking is disabled on the Mac")
00205 //  void operator delete(void* p, LPCSTR lpszFileName, INT32 nLine) {delete p;}
00206 #endif
00207     
00208     // Support functions
00209     static void MemoryTrackAdd(void* p, LPCSTR Filename, INT32 Line);
00210     static void MemoryDump();
00211     static BOOL Init();
00212 
00213 #ifdef _DEBUG
00214     static BOOL CheckMemory( BOOL Assert );
00215 
00216     // Low memory test support
00217     static void EnableLowMemoryTesting();
00218     static void DisableLowMemoryTesting();
00219     static void SetClaimLimit(UINT32 BytesToAllow);
00220     static BOOL GetLowMemoryState() {return FailingMemory;}
00221     static size_t GetLowMemoryLimit() {return BytesBeforeFail;}
00222 
00223 protected:
00224     static size_t BytesBeforeFail;
00225     static BOOL FailingMemory;
00226 
00227 public:
00228     static BOOL CheckMemoryFlag;
00229 
00230 #endif  // _DEBUG
00231 
00232 };
00233 
00234 
00235 // This #define allows new to do all sorts of extra stuff
00237 #ifdef _DEBUG
00238 #if !defined(__WXMAC__)
00239     #define CAM_DEBUG_NEW new(THIS_FILE, __LINE__)
00240 #else
00241 PORTNOTE("MacPort", "Memory tracking is disabled on the Mac")
00242     #define CAM_DEBUG_NEW new
00243 #endif
00244 #else
00245     #define CAM_DEBUG_NEW new
00246 #endif
00247 
00248 
00249 /**********************************************************************************************
00250 
00251 >   class CCObject : public SimpleCCObject
00252 
00253     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00254     Created:    14/7/1993
00255     Base Class: SimpleCCObject
00256     Purpose:    CCObject is derived from SimpleCCObject, so it provides the same new and
00257                 delete operators.  It also provides facilities for dynamic class
00258                 information, and dynamic construction of objects.
00259                 
00260                 You should derive your classes from CCObject, where practical.  To give a
00261                 class dynamic class information, you must do the following:
00262                 
00263                 In your class declaration (preferably at the beginning) you should put:
00264                 MonoOn
00265                 CC_DECLARE_DYNAMIC(MyClass)
00266                 MonoOff
00267                 where MyClass is the name of your class.  Note that there is semi-colon at 
00268                 the end of the line. Then you should put the following in your class 
00269                 definition (.cpp file):
00270                 MonoOn
00271                 CC_IMPLEMENT_DYNAMIC(MyClass, BaseClass)
00272                 MonoOff
00273                 where BaseClass is the name of the class that MyClass is derived from.  This
00274                 may be CCObject, or it may be something else if you have derived your class
00275                 from another class which is in turn derived from CCObject, and so on.
00276                 THe position of this line is not important (as long as it is not inside any
00277                 functions), but it must be present for dynamic class information to work.
00278                 Also note that there is no semi-colon at the end of this line.
00279                 
00280                 Declaring your class as dynamic in this way allows you to test its type
00281                 when you don't know what it will be at runtime.  For example:
00282                 
00283                 MonoOn
00284                 void *GetAnObject();
00285                 
00286                 CCObject *pObject = GetAnObject();
00287                 
00288                 if (pObject->IsKindOf(CC_RUNTIME_CLASS(MyClass))
00289                     do_something;
00290                 else if (pObject->IsKIndOf(CC_RUNTIME_CLASS(Node))
00291                     do_something else;
00292                 else ...
00293                 MonoOff
00294                 
00295                 The special macro CC_RUNTIME_CLASS should be used when trying to identify
00296                 an object at runtime.  It evaluates to a reference to the structure containing
00297                 the runtime class information for the specified class - the IsKindOf() function
00298                 then simply compares pointers to see if the objects are from the same class.
00299                 Therefore this type-checking is quite efficient.
00300                 
00301                 When your class is declared as dynamic, it also means that memory dumps are
00302                 more helpful because instead of saying "CCObject at $247247" they will say
00303                 "MyClass at $247247", so we know exactly what kind of objects are not being
00304                 cleaned up.
00305                 
00306                 Deriving a class from CCObject can be quite an 'expensive' thing to do, as it
00307                 means that the objects have virtual function tables.  However, in debug 
00308                 builds, the dynamic class info can be very useful.  For this reason, there
00309                 are a number of macros which enable you to have dynamic class facilities in
00310                 debug builds, but not in retail builds.  These macros are as follows:
00311                 
00312                 MonoOn
00313                 CC_CLASS_MEMDUMP
00314                 MonoOff
00315                 This macro should be used in class declarations like this:
00316                 
00317                 MonoOn
00318                 class MyClass : public CC_CLASS_MEMDUMP
00319                 {
00320                     ...
00321                 };
00322                 MonoOff
00323                 
00324                 This macro will evaulate to SimpleCCObject in retail builds, and CCObject
00325                 in debug builds.  You then need to use the CC_DECLARE_MEMDUMP and
00326                 CC_IMPLEMENT_MEMDUMP macros in your class declaration and definition.
00327                 These macros are similar to the CC_DECLARE_DYNAMIC and CC_IMPLEMENT_DYNAMIC
00328                 macros described above, and the parameters are the same.  Doing all this gives
00329                 you a class that uses the correct new operator in retail builds, but which
00330                 also provides runtime-classing (and hence more helpful memory diagnostics) in
00331                 debug builds.
00332                 
00333                 \b Dynamic Construction \b0
00334                 
00335                 You may also want to dynamically create objects at run-time, when the type
00336                 of the object you want to create is unknown at compile-time.  An example of
00337                 this is to copy an object.  There are another set of macros that provide all
00338                 the functionality of the CC_..._DYNAMIC macros, but which also provide
00339                 dynamic object creation.  The macros are:
00340                 MonoOn
00341                 CC_DECLARE_DYNCREATE
00342                 CC_IMPLEMENT_DYNCREATE
00343                 MonoOff
00344                 The use and parameters of these macros are the same as for the DYNAMIC macros
00345                 described above.
00346                 
00347                 To copy an object derived from CCObject you need to get the CCRuntimeClass
00348                 object associated with the class, and then call a function of that object
00349                 to create a new one.  For example:
00350                 
00351                 MonoOn
00352                 // Some arbitrary object
00353                 CCObject *pObject = (CCObject *) SomeObject;
00354                 
00355                 // Get the runtime class info on this object
00356                 CCRuntimeClass *pCCRuntimeClass = pObject->GetRuntimeClass();
00357                 
00358                 // Create another object of the same type
00359                 CCObject *pNewObject = pCCRuntimeClass->CreateObject();
00360                 
00361                 // It really is the correct type of object...
00362                 ASSERT(pNewObject(IsKindOf(pCCRuntimeClass)));  // This will succeed
00363                 MonoOff
00364 
00365 
00366     Errors:     -
00367     SeeAlso:    SimpleCCObject; CCRuntimeClass;
00368                 CC_DECLARE_DYNAMIC; CC_IMPLEMENT_DYNAMIC;
00369                 CC_DECLARE_DYNCREATE; CC_IMPLEMENT_DYNCREATE;
00370                 CC_DECLARE_MEMDUMP; CC_IMPLEMENT_MEMDUMP; CC_CLASS_MEMDUMP;
00371                 CC_RUNTIME_CLASS; GetRuntimeClass; IsKindOf; CreateObject;
00372                 AssertValid; Dump
00373 
00374 **********************************************************************************************/
00375 
00376 class CCAPI CCObject : public SimpleCCObject
00377 {
00378 public:
00379 
00380     virtual CCRuntimeClass* GetRuntimeClass() const;
00381     virtual ~CCObject();
00382     static CCRuntimeClass* GetRuntimeClassByName(LPCTSTR pClassName);
00383 
00384 protected:
00385     CCObject();
00386 
00387 private:
00388     CCObject(const CCObject& objectSrc);              
00389     void operator=(const CCObject& objectSrc);       
00390 
00391 public:
00392     BOOL IsKindOf(const CCRuntimeClass* pClass) const;
00393     
00394 // Overridables
00395 //  virtual void Serialize(CArchive& ar) {};
00396 
00397     // Diagnostic Support
00398     virtual void AssertValid() const;
00399 PORTNOTE("other","Removed MFC CDumpContext")
00400 #ifndef EXCLUDE_FROM_XARALX
00401     virtual void Dump( CDumpContext &dc ) const;
00402 #endif
00403 
00404 public:
00405     static CCRuntimeClass cc_classCCObject;
00406     static CCRuntimeClass* GetMyClass();
00407 };
00408 
00409 
00410 /********************************************************************************************
00411 
00412 >   class AutoDeleteCCObject
00413 
00414     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00415     Created:    09/02/05
00416     Purpose:    Simplifies cleanup of temporary CCObject derived objects
00417     SeeAlso:    -
00418 
00419 ********************************************************************************************/
00420 
00421 class AutoDeleteCCObject
00422 {
00423 public:
00424     AutoDeleteCCObject(CCObject* pObj) : m_pObj(pObj) {}
00425     ~AutoDeleteCCObject()
00426     {
00427         if (m_pObj)
00428             delete m_pObj;
00429     }
00430     void Attach(CCObject* pObj)
00431     {
00432         m_pObj = pObj;
00433     }
00434     void Detach()
00435     {
00436         m_pObj = NULL;
00437     }
00438 
00439 protected:
00440     CCObject* m_pObj;
00441 };
00442 
00443 
00444 /********************************************************************************************
00445 
00446 >   Macro IS_SAME_CLASS(pObj1, pObj2)
00447 
00448     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00449     Created:    31/8/94
00450     Inputs:     pObj1, pObj2 - Pointers to the objects to compare.
00451     Returns:    TRUE if both objects are EXACTLY the same class type;
00452                 FALSE if not.
00453     Purpose:    This macro determines whether or not two CCObject-derived objects have the
00454                 same runtime class identifier, i.e. they are of the same class.  This is
00455                 a strict check, unlike IsKindOf(), which follows the inheritance chain.
00456 
00457                 e.g.
00458                 MonoOn
00459                     if (IS_SAME_CLASS(pNode, pOtherNode))
00460                     {
00461                         ...
00462                     }
00463                 MonoOff
00464 
00465     Errors:     If used on a class that does not support runtime classing, it will cause
00466                 a compile-time error.
00467     SeeAlso:    CCObject; CCRuntimeClass; CreateObject; IsKindOf
00468 
00469 ********************************************************************************************/
00470 
00471 #define IS_SAME_CLASS(pObj1, pObj2) \
00472 (((pObj1)->GetRuntimeClass()) == ((pObj2)->GetRuntimeClass()))
00473 
00474 /********************************************************************************************
00475 
00476 >   Macro IS_A(pObj, ClassName)
00477 
00478     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00479     Created:    31/8/94
00480     Inputs:     pObj - Pointer to the object to test (must be CCObject derived, or a
00481                        CCRuntime class object).
00482                 ClassName - Name of the class to test for
00483     Returns:    TRUE if pObj is the same class as, or derived from, the class specified
00484                 by ClassName.
00485     Purpose:    This macro is a convenient shorthand for checking to see if a CCObject-
00486                 derived object is of a particular class.  This is a strict check, unlike 
00487                 IsKindOf(), which follows the inheritance chain.
00488 
00489                 e.g.
00490                 MonoOn
00491                     if (IS_A(pNode, NodeRenderable))
00492                     {
00493                         ...
00494                     }
00495                 MonoOff
00496 
00497     Errors:     If used on a class that does not support runtime classing, it will cause
00498                 a compile-time error.
00499     SeeAlso:    CCObject; CCRuntimeClass; CreateObject; IsKindOf
00500 
00501 ********************************************************************************************/
00502 
00503 #define IS_A(pObj, ClassName) \
00504 (((pObj)->GetRuntimeClass()) == (CC_RUNTIME_CLASS(ClassName)))
00505 
00506 /********************************************************************************************
00507 
00508 >   Macro IS_KIND_OF(ClassName)
00509 
00510     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00511     Created:    31/8/94
00512     Inputs:     ClassName - Name of the class to test for
00513     Returns:    TRUE if pObj is the same class as, or derived from, the class specified
00514                 by ClassName.
00515     Purpose:    This macro is a convenient shorthand for the IsKindOf() function.
00516 
00517                 e.g.
00518                 MonoOn
00519                     if (pNode->IS_KIND_OF(NodeRenderable))
00520                     {
00521                         ...
00522                     }
00523                 MonoOff
00524 
00525     Errors:     If used on a class that does not support runtime classing, it will cause
00526                 a compile-time error.
00527     SeeAlso:    CCObject; CCRuntimeClass; CreateObject; IsKindOf
00528 
00529 ********************************************************************************************/
00530 
00531 #define IS_KIND_OF(ClassName) IsKindOf(CC_RUNTIME_CLASS(ClassName))
00532 
00533 /********************************************************************************************
00534 
00535 >   Macro CC_RUNTIME_CLASS(class_name)
00536 
00537     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00538     Created:    19/7/93
00539     Inputs:     Name of the class
00540     Outputs:    -
00541     Returns:    Pointer to a CCRuntimeClass object
00542     Purpose:    This macro returns a pointer to the CCRuntimeClass object associated with
00543                 the named class.  This structure can be used for determining if an object
00544                 is of a particular type, or for dynamically creating a new object of this
00545                 type.  To use such features, the class must have been declared as
00546                 supporting them with CC_DECLARE_DYNAMIC and so on.
00547     Errors:     If used on a class that does not support runtime classing, it will cause
00548                 a compile-time error.
00549     SeeAlso:    CCObject; CCRuntimeClass; CreateObject; IsKindOf
00550 
00551 ********************************************************************************************/
00552 
00553 #if NEW_RUNTIME_INFO
00554 // DLL version has to call (static) function whose name  gets fixed up
00555 #define CC_RUNTIME_CLASS(class_name) ( class_name::GetMyClass() )
00556 #else
00557 // normal definition
00558 #define CC_RUNTIME_CLASS(class_name) (&class_name::cc_class##class_name)
00559 #endif
00560 
00561 /********************************************************************************************
00562 
00563 >   Macro CC_DECLARE_DYNAMIC(class_name)
00564 
00565     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00566     Created:    19/7/93
00567     Inputs:     Name of the class being declared as dynamic.
00568     Outputs:    -
00569     Returns:    -
00570     Purpose:    Adds declarations to a class which has been derived from CCObject which
00571                 enable it to use runtime classing facilities.
00572 
00573                 NB. Do not have a trailing semi-colon after this macro.
00574 
00575     Errors:     -
00576     SeeAlso:    CC_IMPLEMENT_DYNAMIC; CC_RUNTIME_CLASS; CCObject; CCRuntimeClass
00577 
00578 ********************************************************************************************/
00579 
00580 #define CC_DECLARE_DYNAMIC(class_name) \
00581 public: \
00582     static CCRuntimeClass cc_class##class_name; \
00583     static CCRuntimeClass* GetMyClass(); \
00584     virtual CCRuntimeClass* GetRuntimeClass() const;
00585 
00586 /********************************************************************************************
00587 
00588 >   Macro CC_DECLARE_DYNCREATE(class_name)
00589 
00590     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00591     Created:    19/7/93
00592     Inputs:     -
00593     Outputs:    -
00594     Returns:    -
00595     Purpose:    Adds declarations to a class which has been derived from CCObject which
00596                 enable it to use runtime classing and dynamic object construction facilities.
00597 
00598                 NB. Do not have a trailing semi-colon after this macro.
00599 
00600     Errors:     -
00601     SeeAlso:    CC_IMPLEMENT_DYNCREATE; CC_RUNTIME_CLASS; CCObject; CCRuntimeClass
00602 
00603 ********************************************************************************************/
00604 
00605 #define CC_DECLARE_DYNCREATE(class_name) \
00606     CC_DECLARE_DYNAMIC(class_name) \
00607     static void PASCAL Construct(void* p);
00608 
00609 
00610 /********************************************************************************************
00611 
00612 >   class CC_CLASSINIT
00613 
00614     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00615     Created:    19/7/93
00616     Purpose:    This type is important because it is used to build up the runtime class 
00617                 information used by CCObject and CCRuntimeClass.
00618                 What happens is that any class declared as dynamic has a static instance of
00619                 an object of this type.  This static object is declared by the 
00620                 CC_IMPLEMENT_{DYNAMIC,DYNCREATE} macro.  Declaring this object as static
00621                 means that its constructor is called at program startup (very early on in 
00622                 the initialisation.  The constructor is the important part - the object is
00623                 declared passing in a pointer to the runtime class object (CCRuntimeClass)
00624                 associated with the class in question.  The CC_CLASSINIT then adds this 
00625                 object to the list of classes maintained and used by the CCRuntimeClass
00626                 class.
00627 
00628     SeeAlso:    CCObject; CCRuntimeClass
00629 
00630 ********************************************************************************************/
00631 
00632 class CCAPI CC_CLASSINIT
00633 {
00634 public:
00635     // Constructor
00636     CC_CLASSINIT(CCRuntimeClass* pNewClass);
00637 };
00638 
00639 
00640 
00641 // Implementation of CC_IMPLEMENT_{DYNAMIC,DYNCERATE}
00642 
00643 #define _CC_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
00644     /* Provide textual name of class */ \
00645     static TCHAR BASED_CODE _lpsz##class_name[] = wxT( #class_name ); \
00646     /* Declare runtime class information for this class */ \
00647     CCRuntimeClass class_name::cc_class##class_name = { \
00648         _lpsz##class_name, sizeof(class_name), wSchema, pfnNew, \
00649             CC_RUNTIME_CLASS(base_class_name), NULL }; \
00650     /* Declare the CC_CLASSINIT structure so that the class info is linked in */ \
00651     static CC_CLASSINIT _init_##class_name(&class_name::cc_class##class_name); \
00652     /* Implement GetRuntimeClass() */ \
00653     CCRuntimeClass* class_name::GetRuntimeClass() const \
00654         { return &class_name::cc_class##class_name; } \
00655     /* Implement GetMyClass() (a static function) */ \
00656     CCRuntimeClass* class_name::GetMyClass() \
00657         { return &class_name::cc_class##class_name; } \
00658 // end of _CC_IMPLEMENT_RUNTIMECLASS
00659 
00660 
00661 /********************************************************************************************
00662 
00663 >   CC_IMPLEMENT_DYNAMIC(class_name, base_class_name)
00664 
00665     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00666     Created:    19/7/93
00667     Inputs:     class_name - Name of the class being declared as dynamic.
00668                 base_class_name - Immediate base class of class 'class_name'.
00669     Outputs:    -
00670     Returns:    -
00671     Purpose:    This macro provides the definitions required to make a class dynamic, i.e.
00672                 make it possible to determine its type at runtime.  Note that this macro
00673                 should be used in the .cpp file, and will only work if the class
00674                 declaration (.h file) also uses the CC_DECLARE_DYNAMIC macro.
00675                 
00676                 The base class name is used so that the correct result is returned for
00677                 derived classes, e.g.
00678                 MonoOn
00679                 
00680                 // pObject is really a NodeRenderableInk object
00681                 CCObject *pObject = SomeObject;
00682                 
00683                 // This succeeds because NodeRenderableInk is also a Node because
00684                 // NodeRenderableInk is (ultimately) derived from Node
00685                 ASSERT(pObject->IsKindOf(CC_RUNTIME_CLASS(Node)));
00686                 
00687                 MonoOff
00688                 
00689                 NB. Do not have a trailing semi-colon after this macro.
00690                 
00691     Errors:     -
00692     SeeAlso:    CC_DECLARE_DYNAMIC; CCObject; CCRuntimeClass; 
00693                 CC_RUNTIME_CLASS; GetRuntimeClass; IsKindOf
00694 
00695 ********************************************************************************************/
00696 
00697 #define CC_IMPLEMENT_DYNAMIC(class_name, base_class_name) \
00698     _CC_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
00699 
00700 
00701 /********************************************************************************************
00702 
00703 >   CC_IMPLEMENT_DYNCREATE(class_name, base_class_name)
00704 
00705     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00706     Created:    19/7/93
00707     Inputs:     class_name - Name of the class being declared as dynamic.
00708                 base_class_name - Immediate base class of class 'class_name'.
00709     Outputs:    -
00710     Returns:    -
00711     Purpose:    This macro provides the definitions required to make a class dynamic, i.e.
00712                 make it possible to determine its type at runtime, and to make it possible
00713                 to create an object dynamically without knowing its type at runtime (see
00714                 CCObject for more details).
00715                 Note that this macro should be used in the .cpp file, and will only work if
00716                 the class declaration (.h file) also uses the CC_DECLARE_DYNCREATE macro.
00717 
00718                 The base class name is used so that the correct result is returned for
00719                 derived classes, e.g.
00720                 MonoOn
00721                 
00722                 // pObject is really a NodeRenderableInk object
00723                 CCObject *pObject = SomeObject;
00724                 
00725                 // This succeeds because NodeRenderableInk is also a Node because
00726                 // NodeRenderableInk is (ultimately) derived from Node
00727                 ASSERT(pObject->IsKindOf(CC_RUNTIME_CLASS(Node)));
00728                 
00729                 MonoOff
00730                 
00731                 NB. Do not have a trailing semi-colon after this macro.
00732 
00733     Errors:     -
00734     SeeAlso:    CC_DECLARE_DYNCREATE; CCObject; CCRuntimeClass; 
00735                 CC_RUNTIME_CLASS; GetRuntimeClass; IsKindOf; CreateObject
00736 
00737 ********************************************************************************************/
00738 
00739 #define CC_IMPLEMENT_DYNCREATE(class_name, base_class_name) \
00740     /* Implement the Construct() function */ \
00741     void PASCAL class_name::Construct(void* p) \
00742         { new(p) class_name; } \
00743     _CC_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
00744         class_name::Construct)
00745 // end of CC_IMPLEMENT_DYNCREATE
00746 
00747 
00748 /********************************************************************************************
00749 
00750 <   CC_CLASS_MEMDUMP
00751 <   Runtime Classing
00752 
00753     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00754     Created:    19/7/93
00755     Comment:    This is a macro that is used when runtime class information is desirable in 
00756                 debug builds, but not in retail builds.  Use as follows in your class 
00757                 declaration:
00758                 
00759                 MonoOn
00760                 class MyClass : public CC_CLASS_MEMDUMP
00761                 {
00762                     ...
00763                 };
00764                 MonoOff
00765                 
00766                 This macro evaluates to CCObject in debug builds, i.e. it provides
00767                 dynamic class information, and in retail builds it evaluates to
00768                 SimpleCCObject, i.e. it overrides new and delete, but you don't get the
00769                 dynamic class information, or the overhead of a virtual function table.
00770                 
00771                 It should be used in conjunction with CC_DECLARE_MEMDUMP and
00772                 CC_IMPLEMENT_MEMDUMP.
00773                 
00774                 Using this facility makes memory diagnostics much more detailed, and
00775                 so it is easier to tell which objects are not being cleaned up.
00776                 
00777     SeeAlso:    CC_DECLARE_MEMDUMP; CC_IMPLEMENT_MEMDUMP; CCObject; SimpleCCObject
00778 
00779 ********************************************************************************************/
00780 
00781 #ifdef _DEBUG
00782 #define CC_CLASS_MEMDUMP CCObject
00783 #else
00784 #define CC_CLASS_MEMDUMP SimpleCCObject
00785 #endif
00786 
00787 /********************************************************************************************
00788 
00789 >   Macro CC_DECLARE_MEMDUMP(class_name)
00790 
00791     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00792     Created:    19/7/93
00793     Inputs:     class_name - Name of the class being declared as dynamic.
00794     Outputs:    -
00795     Returns:    -
00796     Purpose:    Used when runtime class information is desirable in debug builds, but
00797                 not in retail builds.  Use as follows in your class declaration:
00798                 
00799                 MonoOn
00800                 class MyClass : public CCObject
00801                 {
00802                     CC_DECLARE_MEMDUMP(MyClass)
00803                     ...
00804                 };
00805                 MonoOff
00806                 
00807                 This macro evaluates to CC_DECLARE_DYNAMIC in debug builds, i.e. it provides
00808                 dynamic class information, and in retail builds it evaluates to nothing,
00809                 i.e. the runtime classing disappears.
00810                 
00811                 It should be used in conjunction with CC_IMPLEMENT_MEMDUMP (and 
00812                 CC_CLASS_MEMDUMP if your class is normally derived from SimpleCCObject).
00813                 
00814                 Using this facility makes memory diagnostics much more detailed, and
00815                 so it is easier to tell which objects are not being cleaned up.
00816 
00817                 NB. Do not have a trailing semi-colon after this macro.
00818 
00819     Errors:     -
00820     SeeAlso:    CC_CLASS_MEMDUMP; CC_IMPLEMENT_MEMDUMP; CCObject; SimpleCCObject
00821 
00822 ********************************************************************************************/
00823 
00824 #ifdef _DEBUG
00825 #define CC_DECLARE_MEMDUMP(class_name) CC_DECLARE_DYNAMIC(class_name)
00826 #else
00827 #define CC_DECLARE_MEMDUMP(class_name)
00828 #endif
00829 
00830 /********************************************************************************************
00831 
00832 >   Macro CC_IMPLEMENT_MEMDUMP(class_name, base_class_name)
00833 
00834     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00835     Created:    19/7/93
00836     Inputs:     class_name - Name of the class being declared as dynamic.
00837                 base_class_name - Immediate base class of class 'class_name'.
00838     Outputs:    -
00839     Returns:    -
00840     Purpose:    Used when runtime class information is desirable in debug builds, but
00841                 not in retail builds.  Use as follows in your class definition (.cpp file):
00842                 
00843                 MonoOn
00844                 CC_IMPLEMENT_MEMDUMP(MyClass, MyBaseClass)
00845                 MonoOff
00846                 
00847                 This macro evaluates to CC_IMPLEMENT_DYNAMIC in debug builds, i.e. it 
00848                 provides dynamic class information, and in retail builds it evaluates to 
00849                 nothing, i.e. the runtime classing disappears.
00850                 
00851                 It should be used in conjunction with CC_DECLARE_MEMDUMP (and 
00852                 CC_CLASS_MEMDUMP if your class is normally derived from SimpleCCObject).
00853                 
00854                 Using this facility makes memory diagnostics much more detailed, and
00855                 so it is easier to tell which objects are not being cleaned up.
00856 
00857                 NB. Do not have a trailing semi-colon after this macro.
00858 
00859     Errors:     -
00860     SeeAlso:    CC_CLASS_MEMDUMP; CC_DECLARE_MEMDUMP; CCObject; SimpleCCObject
00861 
00862 ********************************************************************************************/
00863 
00864 #ifdef _DEBUG
00865 #define CC_IMPLEMENT_MEMDUMP(class_name, base_class_name) \
00866 CC_IMPLEMENT_DYNAMIC(class_name, base_class_name)
00867 #else
00868 #define CC_IMPLEMENT_MEMDUMP(class_name, base_class_name)
00869 #endif
00870 
00871 
00872 
00873 extern "C" void CCAPI CCAssertValidObject(const CCObject* pOb, LPCSTR FileName, INT32 Line);
00874 
00875 
00876 /********************************************************************************************
00877 
00878 >   CC_ASSERT_VALID(CCObject *pObject)
00879 
00880     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00881     Created:    19/7/93
00882     Inputs:     -
00883     Outputs:    -
00884     Returns:    -
00885     Purpose:    This function is used to check the validity of an object - it checks for
00886                 things like NULL pointers, bad segment selectors, incorrect vtable
00887                 pointers etc - see CCAssertValidObject for more details.
00888     Errors:     -
00889     SeeAlso:    CCAssertValidObject
00890 
00891 ********************************************************************************************/
00892 
00893 #ifdef _DEBUG
00894 #define CC_ASSERT_VALID(pOb)  (::CCAssertValidObject(pOb, THIS_FILE, __LINE__))
00895 #else
00896 #define CC_ASSERT_VALID(pOb)  ((void)0)
00897 #endif
00898 
00899 #endif  // INC_CCOBJECT

Generated on Sat Nov 10 03:48:14 2007 for Camelot by  doxygen 1.4.4