// MCMemory.h
//
// Copyright 1998 Diehl Graphsoft, Inc.
// All Rights Reserved.
//
// Cross-platform memory management functions for VectorWorks 9.
//
// Started by Lewis Kapell on 7/15/98.
//
// SourceSafe information for this version:
//    $Revision: 1 $
//    $Date: 6/06/00 6:13p $
//    $Author: Dave $

#ifndef _MCMEMORY_H_
#define _MCMEMORY_H_ 1

#pragma once

#include "GSTypes.h"

#include "MemoryAllocation.h"

// I am hereby inventing a new naming convention: Mem_[function name]
// (this is, of course, subject to revision at any time, by myself or any competent authority).

// The names of these functions are based on the names of Macintosh Memory Manager functions.
// This should make it possible to do a fairly straightforward search-and-replace
// when converting MiniCAD files.

// XXX: Should we use Handle or a new type?
//			What about the already defined GSHandle (GSTypes.h). There is no GSPtr defined
//			yet (don't know why). [DMB 9/4/98]

// 10/6/98  LAK  renamed Handle to MemHandle, to avoid conflict with QuickTime types


/////////////////////////////////////////////////////////////////////////////////////////
// Data types

typedef char* MemPtr;
typedef char** MemHandle;
typedef Uint32 MemSize;


/////////////////////////////////////////////////////////////////////////////////////////
// Nulls

const MemPtr	Mem_NullPtr		= (MemPtr) 0;
const MemHandle	Mem_NullHandle	= (MemHandle) 0;


/////////////////////////////////////////////////////////////////////////////////////////

#if GS_INTERFACE_FACTORING && !GS_CORE_BUILD

	void		GS_COMP_API Mem_SetupMemory();
	void		GS_COMP_API Mem_MaintainMemory();
	void		GS_COMP_API Mem_CleanupMemory();

	MemPtr		GS_COMP_API Mem_NewPtr(MemSize size);
	MemPtr		GS_COMP_API Mem_NewPtrClear(MemSize size);
	void		GS_COMP_API Mem_DisposePtr(MemPtr pointer);
	MemHandle	GS_COMP_API Mem_NewHandle(MemSize size);
	void		GS_COMP_API Mem_DisposeHandle(MemHandle handle);

	MemHandle	GS_COMP_API Mem_NewHandleClear(MemSize size);

	template <class T>
		inline void Mem_DisposeHandleSetNil(T** &h)
			{ Mem_DisposeHandle((MemHandle)h); h = Mem_NullHandle; }

	void		GS_COMP_API Mem_HLock(MemHandle handle);			// ???	might not need these
	void		GS_COMP_API Mem_HUnlock(MemHandle handle);		// ???
	bool		GS_COMP_API Mem_IsHandleLocked(MemHandle handle);

	#define		Mem_HLockHi	Mem_HLock

	Sint8		GS_COMP_API Mem_HGetState(MemHandle handle);
	void		GS_COMP_API Mem_HSetState(MemHandle handle, Sint8 state);

	MemSize		GS_COMP_API Mem_GetHandleSize(MemHandle handle);
	Bool8		GS_COMP_API Mem_SetHandleSize(MemHandle handle, MemSize newSize);
	void		GS_COMP_API Mem_ReduceHandleSize(MemHandle handle, MemSize newSize);

	void		GS_COMP_API Mem_HandToHand(MemHandle &handle);
	void		GS_COMP_API Mem_PtrToHand(MemPtr srcPtr, MemHandle &dstHndl, MemSize size);
	Bool8		GS_COMP_API Mem_PtrToXHand(MemPtr srcPtr, MemHandle dstHndl, MemSize size);	// not used much - can dispense with?
	Bool8		GS_COMP_API Mem_HandAndHand(MemHandle hand1, MemHandle hand2);				// not used much - can dispense with?
	Bool8		GS_COMP_API Mem_PtrAndHand(MemPtr ptr1, MemHandle hand2, MemSize size);

	inline MemHandle GS_COMP_API Mem_CopyHand(MemHandle h) { MemHandle hCopy = h; Mem_HandToHand(hCopy); return hCopy; }

	//#define StripAddress(x) ((MemPtr)(x))			This should go away

	//Bool8 HandleIsLocked(MemHandle handle)		This can probably go away

	//Bool8 HandleIsPurgeable(MemHandle handle)		These can definitely go away
	//Bool8 HandleIsResource(MemHandle handle)


	/////////////////////////////////////////////////////////////////////////////////////////
	// Generic memory manipulation functions.

	void GS_COMP_API Mem_Copy(void *pDest, const void *pSrc, MemSize nBytes);
	void GS_COMP_API Mem_Move(void *pDest, const void *pSrc, MemSize nBytes);
	void GS_COMP_API Mem_Zero(void *pDest, MemSize nBytes);
	void GS_COMP_API Mem_Fill(void *pDest, MemSize nBytes, Uint8 uFill);


	///////////////////////////////////////////////////////////////////////////////
	// Debugging functions - don't call these directly!
	///////////////////////////////////////////////////////////////////////////////

	// Don't do these macro substitutions when compiling MCMemory.cpp itself
	#if BUG
		#ifndef _MCMEMORY_
			#define Mem_NewHandle(s)		Mem_NewHandleDebug(s, THIS_FILE, __LINE__)
			#define Mem_NewHandleClear(s)	Mem_NewHandleClearDebug(s, THIS_FILE, __LINE__)
			#define Mem_SetHandleSize(h, s)	Mem_SetHandleSizeDebug(h, s, THIS_FILE, __LINE__)
		#endif // _MCMEMORY_

		MemHandle GS_COMP_API Mem_NewHandleDebug(MemSize size, const char* file, int line);
		MemHandle GS_COMP_API Mem_NewHandleClearDebug(MemSize size, const char* file, int line);
		Bool8 GS_COMP_API Mem_SetHandleSizeDebug(MemHandle handle, MemSize newSize, const char* file, int line);
	#endif // BUG


	#if 0

		class GS_COMP_API THState
		// Save and restore a handle's state.
		{
			public:
				THState(MemHandle h)	{ fHandle = h; if (h) fHState = HGetState(h); }
				virtual ~THState()		{ if (fHandle) HSetState(fHandle, fHState); }
			
			private:
				Handle		fHandle;
				char		fHState;
		};

		class GS_COMP_API THLock : private THState {
			public:
				THLock(MemHandle h) : THState(h)	{ if (h) Mem_HLock(h); }
		};

		class GS_COMP_API THUnlock : private THState {
			public:
				THUnlock(MemHandle h) : THState(h)	{ if (h) Mem_HUnlock(h); }
		};

	#endif


	/////////////////////////////////////////////////////////////////////////////////////////
	// Map GS_ memory functions to Mem_ memory functions.

	#if !GS_CORE_BUILD

		#define GS_DisposeHandle(cbp, h)		Mem_DisposeHandle(h)
		#define GS_GetHandleSize(cbp, h, sz)	sz = Mem_GetHandleSize(h)
		#define GS_NewHandle(cbp, sz)			Mem_NewHandle(sz)
		#define GS_SetHandleSize(cbp, h, sz)	Mem_SetHandleSize(h, sz)

		#define GS_ReduceHandleSize(cbp, h, sz)	Mem_ReduceHandleSize(h, sz)
		#define GS_HLock(cbp, h)				Mem_HLock(h)
		#define GS_HUnlock(cbp, h)				Mem_HUnlock(h)

		#define GS_GetHandleState(cbp, h, isLocked) isLocked = Mem_IsHandleLocked(h)
		#define GS_SetHandleState(cbp, h, isLocked)	do { if (isLocked) Mem_HLock(h); else Mem_HUnlock(h); } while (0)

	#endif


	/////////////////////////////////////////////////////////////////////////////////////////
	// Temporary backwards compatibility with VectorWorks 8 code. [DMB 9/3/98]

	#if 0
		typedef char* Ptr;

		#ifndef nil
			#define nil							NULL
		#endif

		#define DisposeHandleSetNil(h)			/*Mem_DisposeHandleSetNil(h)*/ h = NULL

		#if !GS_CORE_BUILD
			#define DisposeHandle(h)			/*Mem_DisposeHandle*/((MemHandle)(h))
			#define DisposePtr					Mem_DisposePtr
		#endif

		//#define GetHandleSize					Mem_GetHandleSize  -- Conflicts with Quicktime's - user must explicitly state which one they want.
		#define HGetState(h)					0
		#if !GS_CORE_BUILD && !defined(_RESHANDLER_CPP_)
			#define HLock(h)					/*Mem_HLock*/((MemHandle)(h))
			#define HLockHi(h)					/*Mem_HLock*/((MemHandle)(h))
			#define HUnlock(h)					/*Mem_HUnlock*/((MemHandle)(h))
		#endif

		#if !defined(GS_CORE_BUILD)
		#define HNoPurge(h)						((void)(h))
		#endif

		#define HSetState(h, f)					((void)(h))
		#if !defined(GS_CORE_BUILD)
			#define NewHandleClearGZ			Mem_NewHandleClear
			#define SetHandleSizeCk				Mem_SetHandleSize
		#endif

		#define BlockMoveData(src, dest, sz)	Mem_Move(dest, src, sz)

		#if !GS_CORE_BUILD
		inline MemHandle CopyHandCk(MemHandle h)	{ MemHandle hCopy = h; Mem_HandToHand(hCopy); return hCopy; }
		#endif
	#endif

#else

	/////////////////////////////////////////////////////////////////////////////////////
	// This section is used for Braque. It maps all new VectorWorks 9 memory management
	// functions to old calls for VectorWorks 8.5

	#define Mem_NewPtr					NewPtrCk
	#define Mem_NewPtrClear				NewPtrClearCk
	#define Mem_DisposePtr				DisposePtr

	#define Mem_NewHandle				NewHandleCk
	#define Mem_NewHandleClear			NewHandleClearCk
	#define Mem_DisposeHandle			DisposeHandle
	#define Mem_DisposeHandleSetNil		DisposeHandleSetNil

	#define Mem_HLock					HLock
	#define Mem_HUnlock					HUnlock
	#define Mem_HLockHi					HLockHi

	#define Mem_HGetState				HGetState
	#define Mem_HSetState				HSetState

	#define Mem_GetHandleSize			GetHandleSize
	#define Mem_SetHandleSize			SetHandleSize
	#define Mem_ReduceHandleSize		ReduceHandleSize

	#define Mem_HandToHand				HandToHand
	#define Mem_PtrToHand				PtrToHand
	#define Mem_PtrToXHand				PtrToXHand
	#define Mem_HandAndHand				HandAndHand
	#define Mem_PtrAndHand				PtrAndHand
	#define Mem_CopyHand				CopyHand

	#define Mem_Copy(dest, src, bytes)	BlockMoveData(src, dest, bytes)
	#define Mem_Move(dest, src, bytes)	BlockMoveData(src, dest, bytes)
	#define Mem_Zero(dest, bytes)		Mem_Fill(dest, bytes, 0)
	#define Mem_Fill(dest, bytes, fill)	memset(dest, fill, bytes)

#endif // GS_INTERFACE_FACTORING && !GS_CORE_BUILD

#endif // _MCMEMORY_H_
