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