Bugfix : Zooming works correct, no more errors on screen.
[xara-cairo.git] / wxOil / fixmem.cpp
blob4eeb5f081ce0164809b0fe0f8b4e54e02d97eda8
1 // $Id: fixmem.cpp 1282 2006-06-09 09:46:49Z alex $
2 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
3 ================================XARAHEADERSTART===========================
5 Xara LX, a vector drawing and manipulation program.
6 Copyright (C) 1993-2006 Xara Group Ltd.
7 Copyright on certain contributions may be held in joint with their
8 respective authors. See AUTHORS file for details.
10 LICENSE TO USE AND MODIFY SOFTWARE
11 ----------------------------------
13 This file is part of Xara LX.
15 Xara LX is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License version 2 as published
17 by the Free Software Foundation.
19 Xara LX and its component source files are distributed in the hope
20 that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License along
25 with Xara LX (see the file GPL in the root directory of the
26 distribution); if not, write to the Free Software Foundation, Inc., 51
27 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 ADDITIONAL RIGHTS
31 -----------------
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
35 rights.
37 The additional rights are to use, modify, and distribute the software
38 together with the wxWidgets library, the wxXtra library, and the "CDraw"
39 library and any other such library that any version of Xara LX relased
40 by Xara Group Ltd requires in order to compile and execute, including
41 the static linking of that library to XaraLX. In the case of the
42 "CDraw" library, you may satisfy obligation under the GNU General Public
43 License to provide source code by providing a binary copy of the library
44 concerned and a copy of the license accompanying it.
46 Nothing in this section restricts any of the rights you have under
47 the GNU General Public License.
50 SCOPE OF LICENSE
51 ----------------
53 This license applies to this program (XaraLX) and its constituent source
54 files only, and does not necessarily apply to other Xara products which may
55 in part share the same code base, and are subject to their own licensing
56 terms.
58 This license does not apply to files in the wxXtra directory, which
59 are built into a separate library, and are subject to the wxWindows
60 license contained within that directory in the file "WXXTRA-LICENSE".
62 This license does not apply to the binary libraries (if any) within
63 the "libs" directory, which are subject to a separate license contained
64 within that directory in the file "LIBS-LICENSE".
67 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
68 ----------------------------------------------
70 Subject to the terms of the GNU Public License (see above), you are
71 free to do whatever you like with your modifications. However, you may
72 (at your option) wish contribute them to Xara's source tree. You can
73 find details of how to do this at:
74 http://www.xaraxtreme.org/developers/
76 Prior to contributing your modifications, you will need to complete our
77 contributor agreement. This can be found at:
78 http://www.xaraxtreme.org/developers/contribute/
80 Please note that Xara will not accept modifications which modify any of
81 the text between the start and end of this header (marked
82 XARAHEADERSTART and XARAHEADEREND).
85 MARKS
86 -----
88 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
89 designs are registered or unregistered trademarks, design-marks, and/or
90 service marks of Xara Group Ltd. All rights in these marks are reserved.
93 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
94 http://www.xara.com/
96 =================================XARAHEADEREND============================
99 // fixed memory allocator (used in preference to malloc/free etc)
102 #include "camtypes.h"
103 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
104 #if !defined(__WXMAC__)
105 #include <malloc.h>
106 #else
107 #include <malloc/malloc.h>
108 #endif
109 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
110 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
112 #if !defined(EXCLUDE_FROM_XARLIB)
113 #include "tunemem.h"
114 #endif
116 #if defined( __WXMSW__ )
117 #include <new.h>
118 #elif defined( __WXMAC__ )
119 #include <new>
120 #endif
122 //#include "ralphcri.h" // for critical sections
123 //#define USE_CRIT 1
125 #if !defined(EXCLUDE_FROM_XARLIB)
126 static TunedMemory TheTunedMemoryManager;
127 #endif
129 // Happy chappie critical crappy (for ralphm, threads and so forth)
130 CRITICAL_SECTION CCMallocCriticalSection::sm_Section;
131 BOOL CCMallocCriticalSection::sm_bInit = FALSE;
133 #define checksize(x) FALSE
135 #ifdef _DEBUG
137 typedef struct CCMallocList
139 UINT32 GuardWord;
140 CCMallocList *Next;
141 CCMallocList *Prev;
142 size_t Size;
143 void *Start;
144 char Filename[22];
145 INT32 LineNum;
146 } CCMallocList;
148 static CCMallocList *TraceListHead = NULL;
151 #define MAGIC_LONGWORD 0xDEADBEEF
152 #define MAGIC_EXTRA sizeof(CCMallocList)
155 #ifdef _OUTPUT_DEBUG
156 static INT32 TotalMalloced = 0;
157 #endif
159 /********************************************************************************************
161 static void *CheckMagic( void* Block, BOOL Destroy )
163 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
164 Created: 15/6/94
165 Inputs: Block - pointer to memory block. If Destroy is TRUE will remove magic
166 marker so detect double-freeing.
167 Outputs: None
168 Returns: Pointer before magic in block. Returns NULL if Block was null on input, or
169 if the block is not recognised as one of ours.
170 Purpose: For debug builds to ensure the magic longword marker is in the block.
171 If Destroy is TRUE then removes block from memory tracing list.
172 Stubbed away in retail builds.
173 Scope: Static to fixmem.cpp
175 ********************************************************************************************/
177 static void *CheckMagic( void* Block, BOOL Destroy )
179 if (Block != NULL)
181 CCMallocList *p = (CCMallocList*)Block;
183 // decrement pointer by sizeof(CCMallocList)
184 p--;
186 if ( p->GuardWord == MAGIC_LONGWORD )
188 if (Destroy)
190 p->GuardWord = 0xF000BAAA; // if it was our marker then destroy it
192 if (p == TraceListHead)
193 TraceListHead = p->Next;
195 if (p->Next != NULL)
196 p->Next->Prev = p->Prev;
198 if (p->Prev != NULL)
199 p->Prev->Next = p->Next;
202 else
204 // if marker not there then either we didn't alloc it, or it has been freed for
205 // the second time
206 ENSURE (FALSE, "CCFree/realloc called on memory that was not CCMalloced");
207 return NULL; // so no-one tries to use it
209 Block = p; // use real address to free
211 return Block;
214 /********************************************************************************************
216 static void *StoreMagic( void *Block , UINT32 Size , LPCSTR Filename , INT32 Line )
218 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (and Gerry)
219 Created: 15/6/94
220 Inputs: Block - pointer to memory block. Stores magic longword in there.
221 Outputs: None
222 Returns: The address just past that to the caller for use by the user.
223 Purpose: For debug builds to insert magic longword marker and other memory tracing
224 info in the block. Stubbed away in retail builds.
225 Scope: Static to fixmem.cpp
227 ********************************************************************************************/
229 static void *StoreMagic( void *Block , size_t Size , LPCSTR Filename , INT32 Line )
231 if (Block != NULL)
233 CCMallocList *p = (CCMallocList*)Block;
234 p->GuardWord = MAGIC_LONGWORD; // store magic
236 p->Size = Size;
238 // Fill in the details about the file position
239 if (Filename != NULL)
241 // copy the string passed in and note the line number
242 size_t Count = strlen( Filename );
243 if ( Count>21 )
245 // The string was too long, so we have to copy just the last 22 chars in it
246 Filename += Count-21;
249 // copy the end of the string into the space I have for it
250 strcpy( p->Filename, Filename );
251 p->LineNum = Line;
253 else
255 // set the fields to null values
256 strcpy( p->Filename, "Unknown File" ); // Was a IDS const, but too much effort for debug
257 p->LineNum = 0;
260 p->Start = ((char*)Block) + MAGIC_EXTRA; // and return user bigger pointer
261 return p->Start;
264 return NULL;
268 /********************************************************************************************
270 static void LinkMagic( void *Block )
272 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
273 Created: 1/9/94
274 Inputs: Block - pointer to memory block.
275 Outputs: None
276 Purpose: For debug builds to link the block into the tracking list. Stubbed away in
277 retail builds.
278 Scope: Static to fixmem.cpp
280 ********************************************************************************************/
282 static void LinkMagic( void *Block )
284 if (Block != NULL)
286 CCMallocList *p = (CCMallocList*)Block;
288 p->GuardWord = MAGIC_LONGWORD; // store magic word
290 p->Next = TraceListHead;
291 p->Prev = NULL;
293 if (TraceListHead != NULL)
294 TraceListHead->Prev = p;
296 TraceListHead = p;
301 /********************************************************************************************
303 > void DumpCCMallocTrace(void)
305 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
306 Created: 1/9/94
307 Inputs: None
308 Outputs: None
309 Returns: None
310 Purpose: Lists any unreleased memory blocks
311 Errors: None
312 SeeAlso: LinkMagic;CheckMagic;StoreMagic
314 ********************************************************************************************/
316 void DumpCCMallocTrace(void)
318 if (TraceListHead != NULL)
320 TRACE( _T("\n\n...CCMalloc leaks detected...\n\n"));
322 CCMallocList *Ptr = TraceListHead;
324 while (Ptr != NULL)
326 #if 0 != wxUSE_UNICODE
327 TCHAR pFilename[22];
328 camMbstowcs(pFilename, Ptr->Filename, 22);
329 #else
330 TCHAR* pFilename = Ptr->Filename;
331 #endif
332 TRACE( _T("%ld bytes allocated in %s at line %ld\n"),Ptr->Size, pFilename, Ptr->LineNum);
333 Ptr = Ptr->Next;
336 TRACE( _T("\n...End of CCMalloc leaks...\n\n"));
341 /********************************************************************************************
343 > LPVOID DebugCCMalloc(UINT32 size, LPCSTR Filename, INT32 Line)
345 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
346 Created: 1/9/94
347 Inputs: size of block required
348 source filename called from (supplied by macro)
349 line number of call (supplied by macro)
350 Outputs: None
351 Returns: None
352 Purpose: A version of malloc which does not throw exceptions and provides source file
353 and line number tracing.
354 Errors: Out of memory
355 SeeAlso: RetailCCMalloc;malloc
357 ********************************************************************************************/
359 LPVOID DebugCCMalloc(size_t Size, LPCSTR Filename, INT32 Line)
361 #ifdef USE_CRIT
362 CCMallocCriticalSection Cs;
363 #endif
365 if (Size==0L) // size of 0 is illegal
367 ENSURE(FALSE, "Someone asked for 0 bytes");
368 return NULL;
371 #ifdef _OUTPUT_DEBUG
372 TotalMalloced += Size;
373 TRACE( _T("Malloced %ld (+%ld in %s at line %ld)\n"),TotalMalloced,Size, Filename, Line);
374 #endif
376 size_t NewSize = Size + MAGIC_EXTRA;
378 if (checksize(NewSize))
379 return NULL; // if too big
381 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
382 // if memory runs out
383 #if !defined(__WXMAC__)
384 _PNH old_handler = _set_new_handler( NULL );
385 #else
386 new_handler pnh = set_new_handler(NULL);
387 #endif
389 // call malloc to get the memory or a NULL pointer
390 void *p = malloc( (size_t)NewSize );
392 // The next line is for debug purposes (comment out above line)
393 //void *p = NULL;
395 // repair the function pointer to its old value and return our pointer
396 #if !defined(__WXMAC__)
397 _set_new_handler( old_handler );
398 #else
399 set_new_handler(pnh);
400 #endif
402 // set the error and return if it didn't work
403 if (p == NULL)
405 Error::SetError(_R(IDS_OUT_OF_MEMORY));
406 return NULL;
409 // Link block in to list
410 LinkMagic(p);
412 // TRACE( _T("CCMalloc at 0x%08x (0x%08x)\n"), (char*)p + MAGIC_EXTRA, p);
414 // add the magic longword
415 return StoreMagic(p, Size, Filename, Line);
419 /********************************************************************************************
421 void DebugCCRealloc(LPVOID Buf, UINT32 Size, LPCSTR Filename, INT32 Line)
423 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
424 Created: 1/9/94
425 Inputs: pointer to memory allocated with CCMalloc (or NULL)
426 new size for block
427 source filename called from (supplied by macro)
428 line number of call (supplied by macro)
429 Outputs: None
430 Returns: None
431 Purpose: A version of realloc which does not throw exceptions and provides source file
432 and line number tracing. DO NOT CALL. Use CCRealloc instead.
433 Errors: Out of memory
434 SeeAlso: RetailCCRealloc;realloc
436 ********************************************************************************************/
438 LPVOID DebugCCRealloc(LPVOID Buf, size_t Size, LPCSTR Filename, INT32 Line)
440 #ifdef USE_CRIT
441 CCMallocCriticalSection Cs;
442 #endif
444 if (Size==0L) // size of 0 is illegal
446 ENSURE(FALSE, "Someone asked for 0 bytes");
447 return NULL;
450 // check magic longword (and remove it)
451 const LPVOID NewBuf = CheckMagic(Buf, TRUE); // Unlink block and set deleted
452 if (
453 (NewBuf==NULL) &&
454 (Buf!=NULL)
457 // CheckMagic decided that it wasn't one of our blocks, so don't try to grow it
458 return NULL;
461 size_t NewSize = Size + MAGIC_EXTRA;
463 if (checksize(NewSize))
464 return NULL; // if too big
466 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
467 // if memory runs out
468 #if !defined(__WXMAC__)
469 _PNH old_handler = _set_new_handler( NULL );
470 #else
471 new_handler pnh = set_new_handler(NULL);
472 #endif
474 // call realloc
475 void *p = realloc( NewBuf, (size_t)NewSize );
477 // The next line is for test purposes (comment out above line)
478 //void *p = NULL;
480 // finally repair the function pointer to its old value and return our pointer
481 #if !defined(__WXMAC__)
482 _set_new_handler( old_handler );
483 #else
484 set_new_handler(pnh);
485 #endif
487 // set the error and return if it didn't work
488 if (p == NULL)
490 Error::SetError(_R(IDS_OUT_OF_MEMORY));
492 // Re-link old block into list
493 LinkMagic(NewBuf);
495 // return NULL as realloc
496 return NULL;
498 else
500 // TRACE( _T("CCRealloc at 0x%08x (0x%08x) is now 0x%08x (0x%08x)\n"), Buf, NewBuf, (char*)p+MAGIC_EXTRA, p);
502 // Link new block into list
503 LinkMagic(p);
505 // return result, storing magic word
506 return StoreMagic(p, Size, Filename, Line);
512 /********************************************************************************************
514 > INT32 DebugCCGetBlockSize(LPVOID Block)
516 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
517 Created: 1/5/95
518 Inputs: Block - the alloc'ed block we want to know the size of
519 Returns: the size of the block that was asked for
520 Purpose: Finds out how big a block of ram someone asked for when they called CCMalloc
522 ********************************************************************************************/
524 size_t DebugCCGetBlockSize(LPVOID Block)
526 // default to 0
527 size_t Size = 0;
529 // make sure it is OK
530 if (Block != NULL)
532 // Find out the size
533 CCMallocList *p = (CCMallocList*) (((char*)Block)-MAGIC_EXTRA);
534 Size = p->Size;
537 // return it
538 return Size;
542 #else
543 // retail builds stub out those fns just in case
544 // the only one that is used is CheckMagic (in CCFree)
545 #define CheckMagic(p,k) (p)
546 #define StoreMagic(p,s,f,l) (p)
547 #define LinkMagic(p)
548 #define MAGIC_EXTRA 0
550 /********************************************************************************************
552 LPVOID RetailCCMalloc( UINT32 size )
554 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
555 Created: 1/9/94
556 Inputs: size of memory required (must be non-zero)
557 Outputs: None
558 Returns: Pointer to new block, or NULL if failed.
559 Purpose: Like malloc but does not throw exceptions.
560 Errors: None.
561 SeeAlso: CCFree;RetailCCRealloc;malloc
563 ********************************************************************************************/
565 LPVOID RetailCCMalloc( UINT32 Size )
567 #ifdef USE_CRIT
568 CCMallocCriticalSection Cs;
569 #endif
571 if (Size==0L) // size of 0 is illegal
572 return NULL;
574 if (checksize(Size))
575 return NULL; // if too big
577 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
578 // if memory runs out
579 #if !defined(__WXMAC__)
580 _PNH old_handler = _set_new_handler( NULL );
581 #else
582 new_handler pnh = set_new_handler(NULL);
583 #endif
585 // call malloc to get the memory or a NULL pointer
586 void *p = malloc( (size_t)Size );
588 // repair the function pointer to its old value and return our pointer
589 #if !defined(__WXMAC__)
590 _set_new_handler( old_handler );
591 #else
592 set_new_handler(pnh);
593 #endif
595 // set the error if it didn't work
596 if (p == NULL)
597 Error::SetError(_R(IDS_OUT_OF_MEMORY));
599 return p;
605 /********************************************************************************************
607 LPVOID RetailCCRealloc( LPVOID buf, UINT32 size )
609 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
610 Created: 1/9/94
611 Inputs: Pointer to block allocated with CCMalloc (can be NULL) and new size (must be non-zero)
612 Returns: Pointer to new block (might have changed) or NULL if cannot reallocate (old block
613 will remain intact)
614 Purpose: Change size of memory block, similar to realloc but does not throw exceptions.
615 Errors: None.
616 SeeAlso: RetailCCMalloc;CCFree;realloc
618 ********************************************************************************************/
620 LPVOID RetailCCRealloc( LPVOID Buf, UINT32 Size )
622 #ifdef USE_CRIT
623 CCMallocCriticalSection Cs;
624 #endif
626 if (Size==0L) // size of 0 is illegal
627 return NULL;
629 if (checksize(Size))
630 return NULL; // if too big
632 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
633 // if memory runs out
634 #if !defined(__WXMAC__)
635 _PNH old_handler = _set_new_handler( NULL );
636 #else
637 new_handler pnh = set_new_handler(NULL);
638 #endif
640 // call realloc
641 void *p = realloc( Buf, (size_t)Size );
643 // finally repair the function pointer to its old value and return our pointer
644 #if !defined(__WXMAC__)
645 _set_new_handler( old_handler );
646 #else
647 set_new_handler(pnh);
648 #endif
650 // set the error if it didn't work
651 if (p == NULL)
652 Error::SetError(_R(IDS_OUT_OF_MEMORY));
654 // return result, storing magic word
655 return p;
661 /********************************************************************************************
663 > size_t RetailCCGetBlockSize(LPVOID Block)
665 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
666 Created: 1/5/95
667 Inputs: Block - the alloc'ed block we want to know the size of
668 Returns: the size of the block that was asked for
669 Purpose: Finds out how big a block of ram someone asked for when they called CCMalloc
671 ********************************************************************************************/
673 size_t RetailCCGetBlockSize(LPVOID Block)
675 #ifdef USE_CRIT
676 CCMallocCriticalSection Cs;
677 #endif
679 if (Block==NULL)
680 return 0;
682 #if !defined(__WXMAC__)
683 return _msize(Block);
684 #else
685 return malloc_size(Block);
686 #endif
690 #endif
694 /********************************************************************************************
696 > LPVOID CCMalloc( UINT32 size )
698 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
699 Created: 1/9/94
700 Inputs: size of memory required (must be non-zero)
701 Outputs: None
702 Returns: Pointer to new block, or NULL if failed.
703 Purpose: Like malloc but does not throw exceptions.
704 Errors: None.
705 SeeAlso: malloc;CCFree;CCRealloc
707 ********************************************************************************************/
709 Technical notes:
710 This has been implemented as a macro which calls either RetailCCMalloc or DebugCCMalloc
711 depending on whether it is a retail or debug build.
713 ********************************************************************************************/
716 /********************************************************************************************
718 > LPVOID CCRealloc( LPVOID buf, UINT32 size )
720 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
721 Created: 1/9/94
722 Inputs: Pointer to block allocated with CCMalloc (can be NULL) and new size (must be non-zero)
723 Returns: Pointer to new block (might have changed) or NULL if cannot reallocate (old block
724 will remain intact)
725 Purpose: Change size of memory block, similar to realloc but does not throw exceptions.
726 Errors: None.
727 SeeAlso: RetailCCMalloc;CCFree;realloc
729 ********************************************************************************************/
731 Technical notes:
732 This has been implemented as a macro which calls either RetailCCRealloc or DebugCCRealloc
733 depending on whether it is a retail or debug build.
735 ********************************************************************************************/
738 /********************************************************************************************
740 > void CCFree( LPBYTE buf )
742 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
743 Created: 25/10/93
744 Inputs: pointer to memory allocated with CCMalloc (or NULL)
745 Outputs: None
746 Returns: None
747 Purpose: Like free.
748 Errors: None
749 SeeAlso: CCMalloc;free
751 ********************************************************************************************/
753 void CCFree( LPVOID Buf )
755 #ifdef USE_CRIT
756 CCMallocCriticalSection Cs;
757 #endif
759 #ifdef _OUTPUT_DEBUG
760 if (Buf)
762 CCMallocList* p = (CCMallocList*) Buf;
763 p--;
764 TotalMalloced -= p->Size;
765 TRACE( _T("UnMalloced %ld (-%ld in %s at %ld)\n"),TotalMalloced, p->Size, p->Filename, p->LineNum);
768 #endif
769 // check magic longword (and remove it to find double-frees)
770 Buf = CheckMagic( Buf, TRUE );
772 // TRACE( _T("CCFree at 0x%08x (0x%08x)\n"), Buf, ((char*)Buf - MAGIC_EXTRA));
774 // then free it
775 free( Buf );
781 #if !defined(EXCLUDE_FROM_XARLIB)
782 /********************************************************************************************
784 > TunedMemory* GetTunedMemManager()
786 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
787 Created: 1/5/95
788 Returns: A pointer to the tuned memory manager
789 Purpose: Finds the Tuned Memory manager so that people that need to know get ask
790 it for memory etc
792 ********************************************************************************************/
794 TunedMemory* GetTunedMemManager()
796 return &TheTunedMemoryManager;
798 #endif