#ifndef	PUBLIC_PROTOS_QUARK_AMIGA_H
#define	PUBLIC_PROTOS_QUARK_AMIGA_H

#ifndef  UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif
#ifndef  INTUITION_CLASSES_H
#include <intuition/classes.h>
#endif
#ifndef  INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif



/*
 * Debug Macros
 */

#define kprintf(Fmt, args...) \
	({ULONG _args[] = { args }; RawDoFmt((Fmt), (void*) _args, (void(*)(void)) 0x1, NULL);})

/*
 * Boopsi Macros
 */

#define CallHook(MyHook, MyObject, tags...) \
	({ULONG _tags[] = { tags }; CallHookA((MyHook), (MyObject), (APTR)_tags);})

#define DoMethod(MyObject, tags...) \
	({ULONG _tags[] = { tags }; DoMethodA((MyObject), (APTR)_tags);})

#define DoSuperMethod(MyClass, MyObject, tags...) \
	({ULONG _tags[] = { tags }; DoSuperMethodA((MyClass), (MyObject), (APTR)_tags);})

#define CoerceMethod(MyClass, MyObject, tags...) \
	({ULONG _tags[] = { tags }; CoerceMethodA((MyClass), (MyObject), (APTR)_tags);})

#define SetSuperAttrs(Class, MyObject, tags...)				\
({									\
ULONG		_tags[] = { tags }; 					\
struct opSet	MyopSet;						\
  MyopSet.MethodID	=	OM_SET;					\
  MyopSet.ops_AttrList	=(struct TagItem*) _tags;			\
  MyopSet.ops_GInfo	=	NULL;					\
  DoSuperMethodA((Class), (MyObject), (APTR) &MyopSet);			\
})

/*
 * Replace the intuition.library SetAttrs
 */
#define SETATTRS(MyObject, tags...)					\
({									\
ULONG			_tags[] = { tags }; 				\
struct opSet		MyopSet;					\
  MyopSet.MethodID	=	OM_SET;					\
  MyopSet.ops_AttrList	=(struct TagItem*) _tags;			\
  MyopSet.ops_GInfo	=	NULL;					\
  DoMethodA((MyObject), (APTR) &MyopSet);				\
})

#define GETATTRS(MyObject, AttrID, Ptr)					\
({									\
struct opGet		MyopGet;					\
  MyopGet.MethodID	=	OM_GET;					\
  MyopGet.opg_AttrID	=	AttrID;					\
  MyopGet.opg_Storage	=	Ptr;					\
  DoMethodA((MyObject), (APTR) &MyopGet);				\
})


/*
 * Memory macros
 */

#define	ALLOCVECPOOLED(MyPool,MemSize,SysBase)			\
({								\
ULONG			*MyMemory;				\
ULONG			Size=MemSize;				\
  if (Size == 0)						\
  {								\
    MyMemory	=	NULL;					\
  }								\
  else								\
  {								\
    Size	+=4;						\
    if (MyMemory=(ULONG*) AllocPooled(MyPool,Size))		\
    {								\
      *MyMemory++=Size;						\
    }								\
  }								\
  (void*) MyMemory;						\
})

#define	FREEVECPOOLED(MyPool,MyMemory,SysBase)			\
({								\
  if (MyMemory && MyPool)					\
  {								\
    ULONG	*MemPtr;					\
    ULONG	Size;						\
    MemPtr	=(ULONG*) MyMemory;				\
    Size	=	*--MemPtr;				\
    FreePooled(MyPool,MemPtr,Size);				\
  }								\
})



/*
 * List macros
 */

#define	NEWLIST(MyList)						\
{								\
  (MyList)->lh_TailPred	=(struct Node*) (MyList);		\
  (MyList)->lh_Tail	=(struct Node*) NULL;			\
  (MyList)->lh_Head	=(struct Node*)	&(MyList)->lh_Tail;	\
}

#define	REMHEAD(MyList)							\
({									\
struct Node	*RemovedNode;						\
struct Node	*Result;						\
  if ((RemovedNode=(MyList)->lh_Head)->ln_Succ)				\
  {									\
    (MyList)->lh_Head		=		RemovedNode->ln_Succ;	\
    (MyList)->lh_Head->ln_Pred	=(struct Node*) &(MyList)->lh_Head;	\
    Result	=	RemovedNode;					\
  }									\
  else									\
  {									\
    Result	=	NULL;						\
  }									\
  Result;								\
})


#define	REMTAIL(MyList)							\
({									\
struct	Node	*RemovedNode;						\
struct Node	*Result;						\
  if ((RemovedNode=(MyList)->lh_TailPred)->ln_Pred)			\
  {									\
    (MyList)->lh_TailPred			=		RemovedNode->ln_Pred;						\
    (MyList)->lh_TailPred->ln_Succ	=(struct Node*)	&(MyList)->lh_Tail;						\
    Result	=	RemovedNode;					\
  }									\
  else									\
  {									\
    Result	=	NULL;						\
  }									\
  Result;								\
})

#define	ADDHEAD(MyList,MyNode)						\
{									\
struct Node	*OldHeadNode;						\
  OldHeadNode			=		(MyList)->lh_Head;	\
  (MyNode)->ln_Succ		=		OldHeadNode;		\
  OldHeadNode->ln_Pred		= 		(MyNode);		\
  (MyNode)->ln_Pred		=(struct Node*) (MyList);		\
  (MyList)->lh_Head		=		(MyNode);		\
}

#define	ADDTAIL(MyList,MyNode)						\
{									\
struct Node	*OldPredNode;						\
  OldPredNode		=	(MyList)->lh_TailPred;			\
  (MyNode)->ln_Succ	=(struct Node*)	&(MyList)->lh_Tail;		\
  (MyNode)->ln_Pred	=	OldPredNode;				\
  OldPredNode->ln_Succ	=	(MyNode);				\
  (MyList)->lh_TailPred	=	(MyNode);				\
}


#define	REMOVE(MyNode)							\
({									\
struct Node	*PredNode;						\
struct Node	*SuccNode;						\
  PredNode		=	(MyNode)->ln_Pred;			\
  SuccNode		=	(MyNode)->ln_Succ;			\
  PredNode->ln_Succ	=	SuccNode;				\
  SuccNode->ln_Pred	=	PredNode;				\
  MyNode;								\
})

/*
 * Misc macros
 */

#define	BeginIO(MyIORequest)					\
{								\
struct EmulCaos	MyCaos;					\
  MyCaos.caos_Un.Offset		=	-30;		\
  MyCaos.reg_a1			=(ULONG) MyIORequest;	\
  MyCaos.reg_a6			=(ULONG) ((struct IORequest*) MyIORequest)->io_Device;	\
  (*MyEmulHandle->EmulCallOS)(&MyCaos);			\
}

ULONG	CallHookA(struct Hook *hookPtr, Object *obj, APTR message);

ULONG	DoMethodA(Object*,
                  Msg);

ULONG	DoSuperMethodA(Class*,
                       Object*,
                       Msg);

ULONG	CoerceMethodA(Class*,
                      Object*,
                      Msg);

ULONG	SetSuperAttrsA(Class*,
                       Object*,
                       Msg);

#ifdef AMIGA_ENABLE_NewList
void	NewList(struct List	*MyList);
#else
#define	NewList(a)	NEWLIST(a)
#endif

void*	AllocVecPooled(void	*MyPool,
                       ULONG	Size);

void	FreeVecPooled(void	*MyPool,
                      void	*MyMemory);

BOOL	CheckRexxMsg(struct Message	*rexxmsg);
LONG	GetRexxVar(struct Message	*rexxmsg,
                   UBYTE		*name,
                   UBYTE		**result);
LONG	SetRexxVar(struct Message	*rexxmsg,
                   UBYTE		*name,
                   UBYTE		*value,
                   LONG			length);



#endif
