#ifndef XPKMASTER_QUERY_C
#define XPKMASTER_QUERY_C

/* Routinesheader

	Name:		query.c
	Main:		xpkmaster
	Versionstring:	$VER: query.c 1.0 (06.10.96)
	Author:		SDI
	Distribution:	PD
	Description:	Implementation of XpkQuery

 1.0   06.10.96 : first real version
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include <dos/dos.h>
#include "xpkmaster.h"
#include "xpk_strings.h"

/************************************************************************
 *
 *  Information query
 *
 */

#ifdef __cplusplus
  extern "C"
#endif

LONG __asm XpkQuery(register __a0 struct TagItem *tags)
{
  struct FileInfoBlock	*fib		= 0;
  struct Library	*XpkSubBase	= 0;
  struct XpkInfo	*subinfo;
  struct XpkPackerInfo	*pinfo;
  struct XpkMode	*minfo,
			*modeinfo;
  struct XpkPackerList	*list;
  STRPTR		pname,
			t;
  UBYTE			buf[10],
			libname[30]	= "compressors/xpk____.library";
  LONG			mode,
			result		= XPKERR_NOINFO;

  if((list = (struct XpkPackerList *) findtag(tags, XPK_PackersQuery)))
  {
    BPTR lock = 0;

#ifndef XPK_MINOS_37
    if(!(fib =(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),
    MEMF_PUBLIC)))
      goto Abort1;
#else
    if(!(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
      goto Abort1;
#endif

    memset(list, 0, sizeof(struct XpkPackerList));
    if(!(lock = Lock("libs:compressors", ACCESS_READ)))
      goto Abort1;

    if(!Examine(lock, fib))
      goto Abort1;

    if(fib->fib_DirEntryType < 0)
      goto Abort1;

    while(ExNext(lock, fib))
    {
      STRPTR n = fib->fib_FileName;
      ULONG ID;
      LONG i, l = strlen(n);

      if(l != 14 && l != 15 || strncmp("xpk", n, 3) ||
      strcmp(n + l - 8, ".library"))
	continue;

      n[l - 8] = 0;
      ID = idfromname(n + 3);

      for (i = (LONG) list->xpl_NumPackers; i > 0 &&
      *(ULONG *) list->xpl_Packer[i - 1] > ID; i--)
	*(ULONG *) list->xpl_Packer[i] = *(ULONG *) list->xpl_Packer[i - 1];
      *(ULONG *) list->xpl_Packer[i] = ID;

      if(++list->xpl_NumPackers == MAXPACKERS)
	break;
    }

    result = XPKERR_OK;
  Abort1:
    if(lock)
      UnLock(lock);
    goto Abort;
  }

  if(!(pname = (STRPTR) findtag(tags, XPK_PackMethod)))
  {
    result = XPKERR_BADPARAMS;
    goto Abort;
  }

  sprintf(buf, "%.9s", pname);
  if((t = strchr(buf, '.')))
    *t = 0;
  buf[0] = toupper(buf[0]);
  buf[1] = toupper(buf[1]);
  buf[2] = toupper(buf[2]);
  buf[3] = toupper(buf[3]);

  CopyMem(buf, libname+15, 4);
  if(!(XpkSubBase = OpenLibrary(libname, 0)))
  {
    result = XPKERR_MISSINGLIB;
    goto Abort;
  }

  if(!(subinfo = XpksPackerInfo()))
  {
    result = XPKERR_MISSINGLIB;
    goto Abort;
  }

  if((pinfo = (struct XpkPackerInfo *) findtag (tags, XPK_PackerQuery)))
  {
    sprintf(pinfo->xpi_Name, subinfo->xi_Name);
    sprintf(pinfo->xpi_LongName, subinfo->xi_LongName);
    sprintf(pinfo->xpi_Description, subinfo->xi_Description);
    pinfo->xpi_Flags = subinfo->xi_Flags;
    pinfo->xpi_MaxChunk = subinfo->xi_MaxPkInChunk;
    pinfo->xpi_DefChunk = subinfo->xi_DefPkInChunk;
    pinfo->xpi_DefMode = subinfo->xi_DefMode;
  }
  else if((minfo = (struct XpkMode *) findtag(tags, XPK_ModeQuery)))
  {
    mode = findtag(tags, XPK_PackMode);

    modeinfo = subinfo->xi_ModeDesc;
    while(modeinfo && modeinfo->xm_Upto < mode)
      modeinfo = modeinfo->xm_Next;

    if(!modeinfo)
    {
      result = XPKERR_NOINFO;
      goto Abort;
    }

    CopyMem(modeinfo, minfo, sizeof(struct XpkMode));
  }
  else
  {
    result = XPKERR_BADPARAMS;
    goto Abort;
  }

  result = XPKERR_OK;
Abort:
  if(fib)
  {
#ifndef XPK_MINOS_37
    FreeMem(fib, sizeof(struct FileInfoBlock));
#else
    FreeDosObject(DOS_FIB, fib);
#endif
  }

  if((t = (STRPTR) findtag(tags, XPK_GetError)))
    if(result)
      sprintf(t, TXT_COULD_NOT_GET_INFORMATION);
    else if(!fib)
      sprintf(t, TXT_OUT_OF_MEMORY);
    else
      sprintf(t, TXT_OK);

  if(XpkSubBase)
    CloseLibrary(XpkSubBase);
  return result;
}
#endif /* XPKMASTER_QUERY_C */

