#ifndef XPKMASTER_HOOK_C
#define XPKMASTER_HOOK_C

/* Routinesheader

	Name:		hook.c
	Main:		xpkmaster
	Versionstring:	$VER: hook.c 1.0 (05.10.96)
	Author:		SDI
	Distribution:	PD
	Description:	Hook handling functions

 1.0   05.10.96 : first real version
*/

#include <exec/types.h>
#include "xpkmaster.h"

#ifndef XPK_MINOS_37
typedef ULONG __asm (*regfunc) (register __a0 struct Hook *,
			register __a1 APTR,
			register __a2 APTR
#ifdef SUPPORT_A4
			,register __a4 ULONG
#endif
			);

ULONG __asm MyCallHookPkt(register __a0 struct Hook *hook,
register __a1 APTR paramPacket A4PROTO)
{
  if(!hook)
    return 0;

  return (*(regfunc) hook->h_Entry) (hook, paramPacket, NULL A4SUPP);
}
#endif

#ifdef DEBUG
static STRPTR action_names[8] =
{"<zero>", "XIO_READ", "XIO_WRITE", "XIO_FREE", "XIO_ABORT", "XIO_GETBUF",
"XIO_SEEK", "XIO_TOTSIZE" };
#endif

/*************************** read from input hook ************************/

APTR hookread(struct XpkBuffer *xbuf, ULONG action, APTR buf, ULONG size)
{
  LONG res;

  xbuf->xb_RMsg.xmm_Type = action;
  xbuf->xb_RMsg.xmm_Ptr = (STRPTR) buf;
  xbuf->xb_RMsg.xmm_Size = size;

  if((res = MyCallHookPkt(xbuf->xb_RHook, &xbuf->xb_RMsg A4SUPP2)))
  {
    xbuf->xb_Result = res;
    xbuf->xb_Result2 = xbuf->xb_RMsg.xmm_IOError;
  }

  if(xbuf->xb_Result)
  {
#ifdef DEBUG
    DebugError("hookread: %s <%ld> (%ld)", action_names[(action&7)], action,
    xbuf->xb_Result);
#endif
    return NULL;
  }
  else if (xbuf->xb_RMsg.xmm_Ptr)
    return (APTR) xbuf->xb_RMsg.xmm_Ptr;
  else
    return (APTR) 42;	/* SEEK may return 0 an success!  :-( */
}


/*************************** write to output hook ************************/

APTR hookwrite(struct XpkBuffer *xbuf, ULONG action, APTR buf, ULONG size)
{
  LONG res;

  xbuf->xb_WMsg.xmm_Type = action;
  xbuf->xb_WMsg.xmm_Ptr = (STRPTR) buf;
  xbuf->xb_WMsg.xmm_Size = size;

  if((res = MyCallHookPkt(xbuf->xb_WHook, &xbuf->xb_WMsg A4SUPP2)))
  {
    xbuf->xb_Result = res;
    xbuf->xb_Result2 = xbuf->xb_WMsg.xmm_IOError;
  }
  else if(action == XIO_WRITE)
    xbuf->xb_OutLen += size;

  if(xbuf->xb_Result)
  {
#ifdef DEBUG
    DebugError("hookwrite: %s <%ld> (%ld)", action_names[(action&7)], action,
    xbuf->xb_Result);
#endif
    return NULL;
  }
  else if(xbuf->xb_WMsg.xmm_Ptr)
    return (APTR) xbuf->xb_WMsg.xmm_Ptr;
  else
    return (APTR) 42;	/* SEEK may return 0 an success!  :-( */
}

/*********************** copy data from in to out hook **********************/

LONG copydata (struct XpkBuffer *xbuf, ULONG insize, ULONG outsize)
{
  STRPTR buf;

  return !(buf = (STRPTR) hookread(xbuf, XIO_READ, NULL, insize)) ||
  !hookwrite(xbuf, XIO_WRITE, buf, outsize);
}

#endif /* XPKMASTER_HOOK_C */
