/*
** our include
*/

#include "psupport.h"

/*
** png error message interface
*/

#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))

static void png_format_buffer(png_structp png_ptr,png_charp buffer,png_const_charp message)
{ static const char png_digit[] = {
   '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
  };
  int i,c;

  i = 0;
  do {
    c = png_ptr->chunk_name[i];
    if (isnonalpha(c)) {
      *buffer++ = '[';
      *buffer++ = png_digit[(c >> 4) & 0xf];
      *buffer++ = png_digit[(c >> 0) & 0xf];
      c = ']';
    }
    *buffer++ = c;
  } while(++i < 4);

  if (message) {
    *buffer++ = ':';
    *buffer++ = ' ';
    i = 63; do;while((*buffer++=*message++) && --i);
  }
  *buffer = 0;
}

static void showmsg(png_structp png_ptr,png_const_charp title,png_const_charp message)
{ dt_client_mgr *mgr = (dt_client_mgr *)png_ptr->error_ptr;
  struct ClassBase *cb;
  APTR win;

  if (*message && mgr->verbose) {

    if (cb=mgr->cb,(win=((struct Process *)FindTask(NULL))->pr_WindowPtr) != (APTR)-1) {

      struct EasyStruct *es = &mgr->es;

      es->es_StructSize   = 5 * sizeof(ULONG);
      es->es_Flags        = 0;
      es->es_Title        = (UBYTE *)title;
      es->es_TextFormat   = (UBYTE *)message;
      es->es_GadgetFormat = "OK";

      EasyRequestArgs(win,es,NULL,NULL);
    }
  }
}

void png_error(png_structp png_ptr,png_const_charp message)
{
  showmsg(png_ptr,"PNGdt Error",message); longjmp(png_ptr->jmpbuf,1);
}

void png_chunk_error(png_structp png_ptr,png_const_charp message)
{ char msg[2+18+64];

  png_format_buffer(png_ptr,msg,message); png_error(png_ptr,msg);
}

void png_warning(png_structp png_ptr,png_const_charp message)
{
  showmsg(png_ptr,"PNGdt Warning",message);
}

void png_chunk_warning(png_structp png_ptr,png_const_charp message)
{ char msg[2+18+64];

  png_format_buffer(png_ptr,msg,message); png_warning(png_ptr,msg);
}

void
png_set_error_fn(png_structp png_ptr,png_voidp error_ptr,png_error_ptr error_fn,png_error_ptr warning_fn)
{
  png_ptr->error_ptr  = error_ptr;
  png_ptr->error_fn   = error_fn;
  png_ptr->warning_fn = warning_fn;
}

/*
** png decompression input interface
*/

void png_read_data(png_structp png_ptr,png_bytep data,png_size_t length)
{ dt_client_mgr *mgr = (dt_client_mgr *)png_ptr->error_ptr;
#if 0
  struct ClassBase *cb = mgr->cb;
  if (SetSignal(0,SIGBREAKF_CTRL_E)&SIGBREAKF_CTRL_E)
    { mgr->error = ERROR_BREAK; png_error(png_ptr,"Read Error"+10); }
#endif
  if (FFRRead(mgr->handle,data,length) != length)
    png_error(png_ptr,"Read Error");
}

/*
** png memory managment interface
*/

voidpf png_zalloc(voidpf png_ptr,uInt items,uInt size)
{ png_uint_32 num_bytes = (png_uint_32)items * size;

  return png_memset(png_malloc(png_ptr,num_bytes),0,(png_size_t)num_bytes);
}

void png_zfree(voidpf png_ptr,voidpf ptr)
{
   png_free((png_structp)png_ptr,(png_voidp)ptr);
}

#define cb ((struct ClassBase *)mgr->cb)

png_voidp png_malloc(png_structp png_ptr,png_uint_32 size)
{ dt_client_mgr *mgr = (dt_client_mgr *)png_ptr->error_ptr;
  png_uint_32 *ret = AllocPooled(mgr->pool,size+=sizeof(size));

  if (!ret) {
    mgr->error = ERROR_NO_FREE_STORE; png_error(png_ptr,"Out of Memory");
  }

  *ret++ = size; return ret;
}

void png_free(png_structp png_ptr,png_voidp ptr)
{
  if (ptr) {

    dt_client_mgr *mgr = (dt_client_mgr *)png_ptr->error_ptr;
    png_uint_32 *p = (png_uint_32 *)ptr-1;

    FreePooled(mgr->pool,p,*p);
  }
}

#undef SysBase

png_voidp png_create_struct(int type)
{ ULONG size;

  if ((size=sizeof(png_info),type==PNG_STRUCT_INFO) ||
      (size=sizeof(png_struct),type==PNG_STRUCT_PNG))
    return AllocVec(size,MEMF_CLEAR);
  return NULL;
}

void png_destroy_struct(png_voidp struct_ptr)
{ 
  if (struct_ptr) FreeVec(struct_ptr);
}
