/*
	DIRFN.C:	DOS disk directory functions for MSC 4.0

	Copyright 1987,1988 Michael J. Housky
	Released to the public domain: Aug 20, 1988 by Michael J. Housky
*/

/* ***temp*** are these really necessary?
#include <ctype.h>
#include <direct.h>
#include <errno.h>
#include <string.h>
*/
#include <stdio.h>		/* only used for NULL definition */
#include <dos.h>
#include <stdlib.h>

#include "dirfn.h"

/* ------------	Macros: */

#if !defined(STATIC)	/* debug switch to make locals public for symdeb */
#define STATIC static
#else
#undef STATIC
#define STATIC /* static */
#endif


/*.PA*/
/*
	cur_dta:	Return current DTA address.

Input:
	(none)

Return:
	Return far pointer to current DTA.

*/

char far *cur_dta();

char far *cur_dta( )
{
    union REGS	regs;		/* registers for DOS call */
    struct SREGS
		sregs;		/* segment registers */
    char	far *pd;	/* pointer to DTA */

    regs.h.ah = 0x2F;			/* function = Get DTA */
    intdosx( &regs, &regs, &sregs );
    FP_SEG(pd) = sregs.es;		/* get seg part of DTA */
    FP_OFF(pd) = regs.x.bx;		/* get offset of DTA */
    return pd;				/* return far DTA pointer */

} /* cur_dta */


/*.PA*/
/*
	set_dta:	Set DOS Disk Transfer Address.

Input:
	pdta	= far pointer to DTA.

Return:
	Return far pointer to current DTA.

*/

void set_dta( char far * );

void set_dta( pdta )
    char	far *pdta;	/* pointer to new DTA */
{
    union REGS	regs;		/* registers for DOS call */
    struct SREGS
		sregs;		/* segment registers */
    char	far *pd;	/* pointer to DTA */

    regs.h.ah = 0x1A;			/* function = Set DTA */
    regs.x.dx = FP_OFF(pdta);		/* set DS:DX = DTA address */
    sregs.ds  = FP_SEG(pdta);
    intdosx( &regs, &regs, &sregs );
    return; 

} /* set_dta */


/*.PA*/
/*
	dir_sscan:	Start a directory scan.

Input:
	pdta:	Pointer to directory search DTA, or NULL to have
		 the area malloc'ed.
	fn:	Filespec to match, includes d:path if desired.
	attr:	Attribute to match, zero for normal search.
Output:
	Starts directory scan, if good filespec and any match.
	
Return:
	Result is pointer to DTA, containing first file found, or NULL
	if and error was encountered. (No file found, bad disk or path,
	etc.)
*/

FIND_DTA *dir_sscan( pdta, fn, attr )
    FIND_DTA	*pdta;		/* pointer to caller's DTA struct, or NULL */
    char	*fn;		/* drive:path\filename to match */
    int		attr;		/* attribute bits to match */
{
    union REGS	regs;		/* registers for DOS call */
    struct SREGS
		sregs;		/* segment registers */
    FIND_DTA	*pd,		/* pointer to find file DTA */
		far *fpd;	/* far pointer to Find file DTA */
    char	far *ffn;	/* far pointer to fname */
    char	far *old_dta;	/* save area for current DTA */

    if ( pdta==NULL )
    {

	pd = (FIND_DTA*) malloc( sizeof(FIND_DTA) );
	if ( pd==NULL )
	    return pd;
    }
    else
	pd = pdta;
    fpd = (FIND_DTA far *) pd;		/* make far DTA pointer */
    ffn = (char far *) fn;		/* make far fname pointer */

    old_dta = cur_dta();
    set_dta( (char far *) fpd );

    regs.h.ah = 0x4E;			/* function = Find first */
    regs.x.cx = attr;			/* CX = attribute */
    regs.x.dx = FP_OFF(ffn);		/* ds:dx = fname pointer */
    sregs.ds  = FP_SEG(ffn);
    intdosx( &regs, &regs, &sregs );
    set_dta( old_dta );			/* restore old DTA */
    if ( regs.x.cflag )			/* test for error */
    {
	if ( pdta==NULL )		/* was DTA malloc'ed? */
	    free( (char*) pd );		/*  free it if so */
	return NULL;			/* return NULL in any case */
    }
    return pd;				/* good result, return DTA pointer */

} /* dir_sscan */


/*.PA*/
/*
	dir_cscan:	Continue a directory scan.

Input:
	pdta	= Pointer to DTA established by prior dir_sscan call.

Return:
	Return (pdta) if next file found, and *pdta contains description
	of file.
	Return NULL if error encountered. (No more matching files, etc.)
*/

FIND_DTA *dir_cscan( pdta )
    FIND_DTA	*pdta;		/* pointer to caller's DTA struct, or NULL */
{
    union REGS	regs;		/* registers for DOS call */
    struct SREGS
		sregs;		/* segment registers */
    FIND_DTA	
		far *fpd;	/* far pointer to Find file DTA */
    char	far *old_dta;	/* save area for current DTA */

    fpd = (FIND_DTA far *) pdta;	/* make far DTA pointer */

    old_dta = cur_dta();
    set_dta( (char far *)fpd );

    regs.h.ah = 0x4F;			/* function = Find next */
    intdosx( &regs, &regs, &sregs );
    set_dta( old_dta );			/* restore old DTA */
    if ( regs.x.cflag )			/* test for error */
	return NULL;			/*  return NULL if so */
    return pdta;			/* good result, return DTA pointer */

} /* dir_cscan */

