#ifndef _COMMON_SMARTPOINTER_HPP_
#define _COMMON_SMARTPOINTER_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif

class PointerDisposition
{
public:
  enum Disposition{Assume,Delete};
};

template <class T>
class SmartPointer
{
public:
	SmartPointer(void);
	SmartPointer(T FAR *lpSmartPointer,PointerDisposition::Disposition disposition=PointerDisposition::Assume);
	SmartPointer(const SmartPointer<T> &someSmartPointer);
	virtual ~SmartPointer();
	T FAR *operator->(void);
	operator T FAR *(void);
	operator LPARAM(void);
	SmartPointer<T> &operator=(const SmartPointer<T> &someSmartPointer);
	SmartPointer<T> &operator=(T FAR *lpSmartPointer);
	WORD operator==(const SmartPointer<T> &someSmartPointer)const;
	void disposition(PointerDisposition::Disposition disposition);
	PointerDisposition::Disposition disposition(void)const;
  void destroy(void);
	bool isOkay(void)const;
	bool isNull(void)const;
protected:
  T **ppt(void);
private:
	T FAR *mlpSmartPointer;
	PointerDisposition::Disposition mDisposition;
};

template <class T>
inline
SmartPointer<T>::SmartPointer(void)
: mlpSmartPointer(0), mDisposition(PointerDisposition::Assume)
{
}

template <class T>
inline
SmartPointer<T>::SmartPointer(T FAR *lpSmartPointer,PointerDisposition::Disposition disposition)
: mlpSmartPointer(lpSmartPointer), mDisposition(disposition)
{
}

template <class T>
inline
SmartPointer<T>::SmartPointer(const SmartPointer<T> &someSmartPointer)
: mlpSmartPointer(0), mDisposition(PointerDisposition::Assume)
{
	*this=someSmartPointer;
}

template <class T>
inline
SmartPointer<T>::~SmartPointer()
{
	destroy();
}

template <class T>
inline
SmartPointer<T>::operator T FAR *(void)
{
	return mlpSmartPointer;
}

template <class T>
inline
T **SmartPointer<T>::ppt(void)
{
  return &mlpSmartPointer;
}

template <class T>
inline
SmartPointer<T>::operator LPARAM(void)
{
	return (LPARAM)mlpSmartPointer;
}

template <class T>
inline
T FAR *SmartPointer<T>::operator->(void)
{
	return mlpSmartPointer;
}

template <class T>
inline
SmartPointer<T> &SmartPointer<T>::operator=(const SmartPointer<T> &someSmartPointer)
{
	destroy();
	mlpSmartPointer=someSmartPointer.mlpSmartPointer;
	mDisposition=PointerDisposition::Assume;
	return *this;
}

template <class T>
inline
SmartPointer<T> &SmartPointer<T>::operator=(T FAR *lpSmartPointer)
{
	destroy();
	mlpSmartPointer=lpSmartPointer;
	mDisposition=PointerDisposition::Assume;
	return *this;
}

template <class T>
inline
WORD SmartPointer<T>::operator==(const SmartPointer<T> &someSmartPointer)const
{
	return *mlpSmartPointer==*someSmartPointer.mlpSmartPointer;
}

template <class T>
inline
void SmartPointer<T>::destroy(void)
{
	if(!mlpSmartPointer)return;
	if(PointerDisposition::Assume==mDisposition)mlpSmartPointer=0;
	else {::delete mlpSmartPointer;mlpSmartPointer=0;}
}

template <class T>
inline
void SmartPointer<T>::disposition(PointerDisposition::Disposition disposition)
{
  mDisposition=disposition;
}

template <class T>
inline
PointerDisposition::Disposition SmartPointer<T>::disposition(void)const
{
	return mDisposition;
}

template <class T>
inline
bool SmartPointer<T>::isNull(void)const
{
  return (mlpSmartPointer?FALSE:TRUE);
}

template <class T>
inline
bool SmartPointer<T>::isOkay(void)const
{
  return !isNull();
}
#endif
