00001 // $Id: handles.cpp 1467 2006-07-18 17:00:07Z gerry $ 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 // Keeps track of handles onto memory blocks and pointers 00099 00100 /* 00101 A Log of the addidtions to this source file 00102 00103 */ 00104 00105 00106 #include "camtypes.h" 00107 //#include "handles.h" // include the header file - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 //#include "memblk.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 00111 00112 /*==========================================================================================*/ 00113 00114 00115 // The Handle Array 00116 00117 typedef struct HandleTableStruct { 00118 ADDR Address; // The address of the block 00119 #ifdef USE_UNIQUE_IDS 00120 WORD UniqueID; // Helps to keep Handles unique 00121 // char Kludge[8-sizeof(ADDR)-sizeof(WORD)]; // Make the struct a power of 2 in length 00122 char Kludge[(2*sizeof(ADDR))-sizeof(ADDR)-sizeof(WORD)]; // Make the struct a power of 2 in length 00123 #endif 00124 } HandleTableElement; 00125 00126 #define HandleTableSize 500 // Number of handles per table 00127 #define HandleTableElementSize (sizeof( HandleTableElement )) 00128 // The size of each element in the table 00129 00130 #define HandleTableByteSize (HandleTableSize * HandleTableElementSize) 00131 00132 MemoryBlock HandlesMemory; // actual memory for handles array 00133 00134 HandleTableElement* HandlesTable; // Array of Handles + Other info 00135 static UINT32 HandleTableTotalSize; // Total size of the table to date 00136 static UINT32 ElementsInHandleTable; // The total number of elements in the table 00137 static UINT32 HandlesInUse; // The Number of Handles currently in use 00138 #ifdef USE_UNIQUE_IDS 00139 static WORD CurrUniqueId = 1; // The Current ID is incremented each time 00140 // a handle is issued. 00141 #endif 00142 00143 00144 00145 /*==========================================================================================*/ 00146 00147 /********************************************************************************************* 00148 00149 > BOOL InitHandles() 00150 00151 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00152 Created: 27/04/93 00153 Returns: TRUE if all went OK, FALSE otherwise 00154 Purpose: Starts up the Handles stuff. It sets all the handles in the table to 00155 sensible starting values and inits a count of the number of handles 00156 00157 *********************************************************************************************/ 00158 00159 BOOL InitHandles() 00160 { 00161 // Try and get some memory from the OS for my lovely table 00162 HandleTableTotalSize = HandleTableByteSize; 00163 ElementsInHandleTable = HandleTableSize; 00164 HandlesInUse = 0; 00165 HandlesTable = (HandleTableElement*) 00166 HandlesMemory.Init( HandleTableTotalSize, TRUE, MEMORYBLOCK_RELOCHEAP); 00167 00168 // check to see if we got the ram needed 00169 if (HandlesTable==NULL) 00170 return FALSE; 00171 00172 // init all the elements in the table to a non-existent handle 00173 for (UINT32 n=0; n<ElementsInHandleTable; n++) 00174 { 00175 // Set the Address to Bad 00176 HandlesTable[n].Address = PBYTE(BAD_MHANDLE); 00177 00178 // if we are using unique IDs, set it to zero 00179 #ifdef USE_UNIQUE_IDS 00180 HandlesTable[n].UniqueID = 0; 00181 #endif 00182 } 00183 00184 // All worked 00185 return TRUE; 00186 } 00187 00188 00189 00190 00191 00192 00193 /********************************************************************************************* 00194 00195 > void DeinitHandles() 00196 00197 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00198 Created: 27/04/93 00199 Purpose: Closes down the Handles manager. Should free up any space allocated 00200 by the Handle Manager during it life 00201 00202 *********************************************************************************************/ 00203 00204 void DeinitHandles() 00205 { 00206 #ifdef _DEBUG 00207 // Tell me how many handles were in use at its peak 00208 TRACE( wxT("DeinitHandles: Max size of handle table = %ld"), ElementsInHandleTable ); 00209 00210 // Tell everyone about any handles that were not released 00211 UINT32 Waste = 0; 00212 for (UINT32 n=1; n<ElementsInHandleTable; n++) 00213 { 00214 if (HandlesTable[n].Address != BAD_MHANDLE ) 00215 { 00216 TRACE( wxT("Handle %d not released (0x%08x)"), n, HandlesTable[n].Address); 00217 Waste++; 00218 } 00219 } 00220 TRACE( wxT("DeinitHandles: %ld handles not released"), Waste ); 00221 #endif 00222 00223 // dealloc the memory we now have from the OS 00224 HandlesMemory.DeInit(); 00225 } 00226 00227 00228 00229 00230 /********************************************************************************************* 00231 00232 > ADDR DescribeHandle( MHANDLE Handle ) 00233 00234 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00235 Created: 27/04/93 00236 Inputs: A Handle to a memory location 00237 Returns: The address associated with the handle supplied 00238 Purpose: To get an up to date location of the memory location 00239 00240 *********************************************************************************************/ 00241 00242 ADDR DescribeHandle( MHANDLE Handle ) 00243 { 00244 #ifdef USE_UNIQUE_IDS 00245 ENSURE( (Handle & 0xFFFF) > BAD_MHANDLE, "DescribeHandle: Handle was Bad" ); 00246 ENSURE( (Handle & 0xFFFF) < ElementsInHandleTable, "DescribeHandle: Handle out of range" ); 00247 #else 00248 ENSURE(Handle > BAD_MHANDLE, "DescribeHandle: Handle was Bad" ); 00249 ENSURE(Handle < ElementsInHandleTable, "DescribeHandle: Handle out of range" ); 00250 #endif 00251 00252 // passed all the assertions, but make no checks that the addr being returned 00253 // is valid. If it is not then they will be passed BAD_MHANDLE 00254 00255 // Must also check that the Unique ID in the Handle is the same as the one in the 00256 // Handle table, but only if USE_UNIQUE_IDS is defined 00257 00258 00259 #ifdef USE_UNIQUE_IDS 00260 // Have to decode the handles 00261 if ((HIWORD(Handle)) != (HandlesTable[LOWORD(Handle)].UniqueID)) 00262 return BAD_MHANDLE; 00263 else 00264 return HandlesTable[LOWORD(Handle)].Address; 00265 00266 #else 00267 // the more efficent version, with no unique ID passing 00268 return HandlesTable[Handle].Address; 00269 #endif 00270 } 00271 00272 00273 00274 00275 /********************************************************************************************* 00276 00277 > BOOL ReleaseHandle( MHANDLE Handle ) 00278 00279 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00280 Created: 27/04/93 00281 Inputs: A Handle that is currently in use 00282 Returns: A BOOL to say if the release of the Handle was succesful 00283 Purpose: To free up a handle that is no longer required by its user 00284 Notes: There are 2 versions of this function below - one is used if 00285 USE_UNIQUE_IDS is defined and the other if it is not 00286 00287 *********************************************************************************************/ 00288 00289 #ifdef USE_UNIQUE_IDS 00290 BOOL ReleaseHandle( MHANDLE Handle ) 00291 { 00292 // TRACEUSER("Gerry", _T("ReleaseHandle - %d"), Handle); 00293 00294 // make sure its not garbage 00295 ENSURE( (Handle & 0xFFFF) > BAD_MHANDLE, "ReleaseHandle: Handle was bad" ); 00296 ENSURE( (Handle & 0xFFFF) < ElementsInHandleTable, "ReleaseHandle: Handle was bad" ); 00297 00298 WORD LowWord = LOWORD(Handle); 00299 00300 if ( HIWORD(Handle) != HandlesTable[LowWord].UniqueID ) 00301 { 00302 TRACE( _T("ReleaseHandle - Someone tried to release a handle that is not theirs!\n") ); 00303 return FALSE; // Not your handle to release 00304 } 00305 else 00306 { 00307 if (HandlesTable[LowWord].Address != BAD_MHANDLE) 00308 { 00309 // mark it as available 00310 HandlesTable[LowWord].Address = BAD_MHANDLE; 00311 HandlesTable[LowWord].BlockSize = 0; 00312 HandlesTable[LowWord].UniqueID = 0; 00313 HandlesInUse --; 00314 return TRUE; 00315 } 00316 00317 return FALSE; // if we got here, return false 00318 } 00319 } 00320 00321 #else 00322 00323 BOOL ReleaseHandle( MHANDLE Handle ) 00324 { 00325 // TRACEUSER("Gerry", _T("ReleaseHandle - %d"), Handle); 00326 00327 // make sure its not garbage 00328 ENSURE( Handle > BAD_MHANDLE, "ReleaseHandle: Handle was BAD_MHANDLE" ); 00329 ENSURE( Handle < ElementsInHandleTable, "ReleaseHandle: Handle was too big" ); 00330 00331 if ( HandlesTable[Handle].Address != BAD_MHANDLE ) 00332 { 00333 // mark it as available 00334 HandlesTable[Handle].Address = PBYTE(BAD_MHANDLE); 00335 HandlesInUse --; 00336 return TRUE; 00337 } 00338 00339 return FALSE; // if we got here, return false 00340 } 00341 #endif 00342 00343 00344 00345 00346 00347 00348 00349 /********************************************************************************************* 00350 00351 > ADDR AlterHandle( MHANDLE Handle, ADDR Address ) 00352 00353 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00354 Created: 27/04/93 00355 Inputs: Handle - A handle currently in use by the caller 00356 Address - The new memory location to associate with the handle 00357 Size - The new size of the the block 00358 Returns: The old address that used to be associated with the handle 00359 Purpose: The change the location associated with the handle without having to 00360 release and then re-claim a new handle 00361 00362 *********************************************************************************************/ 00363 00364 ADDR AlterHandle( MHANDLE Handle, ADDR Address ) 00365 { 00366 ADDR OldAddr; 00367 00368 #ifdef USE_UNIQUE_IDS 00369 // Make sure its not garbage 00370 ENSURE( LOWORD(Handle) > BAD_MHANDLE, "AlterHandle: Handle was bad" ); 00371 ENSURE( LOWORD(Handle) < ElementsInHandleTable, "AlterHandle: Handle too big" ); 00372 00373 // note old value and change it to the new one 00374 OldAddr = HandlesTable[LOWORD(Handle)].Address; 00375 HandlesTable[ LOWORD(Handle) ].Address = Address; 00376 #else 00377 // make sure its not garbage 00378 ENSURE( Handle > BAD_MHANDLE, "AlterHandle: Handle was bad" ); 00379 ENSURE( Handle < ElementsInHandleTable, "AlterHandle: Handle was too big" ); 00380 00381 // note old value and change it to the new one 00382 OldAddr = HandlesTable[Handle].Address; 00383 HandlesTable[Handle].Address = Address; 00384 #endif 00385 00386 // retrun back the old value 00387 return OldAddr; 00388 } 00389 00390 00391 00392 00393 00394 /********************************************************************************************* 00395 00396 > BOOL RelocateHandles( ADDR LowAddr, ADDR HighAddr, INT32 Shift ) 00397 00398 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00399 Created: 27/04/93 00400 Inputs: LowAddr - The low address in the region supplied 00401 HighAddr - The high address in the region supplied 00402 Shift - The amount to alter all the address in the region by. 00403 Returns: TRUE 00404 Purpose: Finds all the memory locations in the supplied region that have 00405 handles associated with them and modifies the address. Usually called 00406 by the memory manager when it shifts a block of memory to a different 00407 location 00408 00409 *********************************************************************************************/ 00410 00411 BOOL RelocateHandles( ADDR LowAddr, ADDR HighAddr, INT32 Shift ) 00412 { 00413 // Make sure that the params are not rubbish 00414 ENSURE( HighAddr > LowAddr, "RelocateHandles: Low Addr is Higher the High Addr" ); 00415 00416 // Check if nothing needs to be done 00417 if (Shift == 0) 00418 return TRUE; 00419 00420 // Loop through the handles 00421 ADDR Address; 00422 for (UINT32 n=1; n<ElementsInHandleTable; n++) 00423 { 00424 // First out get the address from the array 00425 Address = HandlesTable[n].Address; 00426 00427 if (Address != BAD_MHANDLE) 00428 { 00429 if (Address >= LowAddr && Address < HighAddr) 00430 // If the address is in the range, shift it and store it back in the array 00431 HandlesTable[n].Address = Address + Shift; 00432 } 00433 } 00434 00435 return TRUE; 00436 } 00437 00438 00439 00440 00441 /********************************************************************************************* 00442 00443 > BOOL ReleaseRangeOfHandles( ADDR LowAddr, ADDR HighAddr ) 00444 00445 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00446 Created: 28/04/93 00447 Inputs: LowAddr - The Low address in the range 00448 HighAddr - The High address in the range to be searched 00449 Returns: TRUE 00450 Purpose: Find all the handles that refer to address in the the given range 00451 and release them 00452 00453 *********************************************************************************************/ 00454 00455 BOOL ReleaseRangeOfHandles( ADDR LowAddr, ADDR HighAddr ) 00456 { 00457 // TRACEUSER("Gerry", _T("ReleaseRange - 0x%08x to 0x%08x"), LowAddr, HighAddr); 00458 00459 // Make sure the params are not rubbish 00460 ENSURE( HighAddr > LowAddr, "ReleaseRangeOfHandles: Low Addr is Higher the High Addr" ); 00461 00462 // loop through the table 00463 ADDR Address; 00464 for (UINT32 n=1; n<ElementsInHandleTable; n++) 00465 { 00466 // First out get the address from the array 00467 Address = HandlesTable[ n ].Address; 00468 00469 // if it is ok 00470 if (Address != BAD_MHANDLE) 00471 { 00472 if( Address >= LowAddr && 00473 Address < HighAddr ) 00474 { 00475 // If the address is in the range, release it 00476 // TRACEUSER("Gerry", _T("ReleaseRange - releasing %d"), n); 00477 HandlesTable[n].Address = PBYTE(BAD_MHANDLE); 00478 HandlesInUse --; 00479 } 00480 } 00481 } 00482 00483 return TRUE; 00484 } 00485 00486 00487 /********************************************************************************************* 00488 00489 > MHANDLE ClaimHandle( ADDR Address ) 00490 00491 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00492 Created: 27/04/93 00493 Inputs: Address - The address of a block or somewhere in a block of allocated 00494 memory. 00495 Size - The size of the block of memory being stored. If zero then just 00496 a pointer stored. If this parameter is not passed, then zero 00497 assumed 00498 Returns: A handle to the address or BAD_MHANDLE 00499 Purpose: Allocates a handle to the supplied address. The handle should be used 00500 as the reference to the memory location from then on to allow the 00501 memory manager to move the allocation around 00502 00503 *********************************************************************************************/ 00504 00505 MHANDLE ClaimHandle( ADDR Address ) 00506 { 00507 // Need to scan along the list of handles to find an unused one 00508 if (HandlesInUse == (ElementsInHandleTable-1)) 00509 { 00510 // we have run out of handles 00511 TRACEUSER( "Rik", wxT("ClaimHandle - No more handles available. Trying to get some more\n") ); 00512 00513 // First off we had better try to extend our allocation of memory to the table 00514 // If it fails, return saying there are no more handles left! 00515 if (!HandlesMemory.Grow(HandleTableTotalSize, 00516 HandleTableTotalSize+HandleTableByteSize, (LPVOID*)&HandlesTable )) 00517 { 00518 TRACE( wxT("ClaimHandle - Failed to get more handles!!!! P A N I C\n") ); 00519 return BAD_MHANDLE; 00520 } 00521 00522 // grew handle table OK, Set all the new bits of mem to defaults 00523 for (INT32 i=0; i<HandleTableSize; i++) 00524 HandlesTable[ElementsInHandleTable+i].Address = PBYTE(BAD_MHANDLE); 00525 00526 // increase the counters 00527 HandleTableTotalSize += HandleTableByteSize; 00528 ElementsInHandleTable += HandleTableSize; 00529 } 00530 00531 // Ok, we must have some handles by now, so lets try and find one 00532 UINT32 Handle = ElementsInHandleTable - 1; 00533 while (Handle>0) 00534 { 00535 if (HandlesTable[Handle].Address == BAD_MHANDLE ) 00536 { 00537 // Store the Addr 00538 HandlesTable[Handle].Address = Address; 00539 HandlesInUse ++; 00540 00541 // if we are using unique IDs, do this 00542 #ifdef USE_UNIQUE_IDS 00543 // Using Unique IDS, so get the next id and store it away 00544 WORD UniqueID = CurrUniqueId++; 00545 HandlesTable[ Handle ].UniqueID = UniqueID; 00546 return MAKEINT32( Handle, UniqueID ); 00547 #else 00548 // TRACEUSER("Gerry", _T("ClaimHandle - %d"), Handle); 00549 return Handle; 00550 #endif 00551 } 00552 00553 Handle --; 00554 } 00555 00556 // Should never get here 00557 ENSURE( FALSE, "ClaimHandle: We Should never have reached this bit!" ); 00558 return BAD_MHANDLE; 00559 } 00560