/***********************************************************
	files.c -- collect filenames
***********************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <farstr.h>
/*
#include <io.h>
*/
#include <dos.h>
#include <ctype.h>
#include "lh.h"
#include "errmes.h"

#define MAXPATH 65

int tcount, fcount;

struct fb far *fbuf;
static struct fb far *flst;

/***************************************
	initialize pointers for 
	registing files
***************************************/
static void init_regfile(void)
{
	fbuf = flst = NULL;

	tcount = fcount = 0;
}

/***************************************
	regist file name
***************************************/
static void regfile(char *p, char *q, char *f, long utc)
/*
	p: directory name including drive & base directory
	q: partial directory name following base directory
	f: file name

	"d:pppp/qqqq/\0 ffff\0"
	 ^      ^       ^
	 p      q       f
*/
{
	struct fb far *fp, far *fnxt;
	char far *r, far *t;

	if (strcmp(f, lhtmp1) == 0 || strcmp(f, lhtmp2) == 0)
		return;					/* temporary file ? */
	if (flg_i == 0) {
/*
		strupr(p);
*/
		char *s;

		s = p;
		while (*s) {
			if (iskanji(*s)) s++;
			else *s = toupper(*s);
			if (*s) s++;
		}
	}
	fnxt = e_farmalloc(strlen(p) + strlen(f) + sizeof(struct fb));
	fnxt -> time = utc;
	far_strcpy(r = fnxt -> fname, p);
	far_strcpy(t = fnxt -> fpos = r + strlen(p), f);
	if (flg_x) t = r + (q - p);
	fnxt -> cpos = t;

	for (fp = fbuf; fp != NULL; fp = fp -> nxt) {
		if (far_strcmp(fp -> cpos, t) == 0)	{
			if (far_strcmp(fp -> fname, r) == 0) {
				farfree(fnxt);
				return;
			} else {
				far_strcpy(work, t);
				error(DUPFNERR, work);
							/* same registing names of different files */
			}
		}
	}
	if (flst) {
		flst -> nxt = fnxt;
	} else {
		fbuf = fnxt;
	}
	flst = fnxt;
	flst -> nxt = NULL;
	flst -> used = 0;

	tcount ++;
}

/***************************************
  recursive collection of files
***************************************/
static int travel(char *p, char *q, char *f)
/*
	p: directory name including drive & base directory
	q: directory name following base directory
	f: file name

	"pppp/qqqq/\0 ffff\0"
	 ^    ^       ^
	 p    q       f
*/
{
	struct find_t srchbuf;
	char *r, *s;
	int done, cnt;

/*
	if (f) strupr(f);
*/
	cnt = 0;
	convdelim(p, pathdelim);
	done = _dos_findfirst(p, 0x17, &srchbuf);	/* search the first file */
	convdelim(p, DELIM);
	s = backpath(q);
	while (! done) {
		if (!(srchbuf.attrib & 0x06) || flg_a) {
			if (srchbuf.attrib & 0x10) {	/* if this is a sub-directory */
				if (flg_r) {
					if (srchbuf.name[0] != '.') {
						r = stpcpy(stpcpy(s, srchbuf.name), DELIMSTR "*.*");
						if (r - p > MAXPATH)
							error(TOOLONGERR, p);
						cnt += travel(p, q, f);
							/* search recursively */
						*s = '\0';
					}
				}
			} else {						/* if this is a file */
				if (flg_r != 1 
					|| *matchfname(f, srchbuf.name) == '\0')
				{
					cnt++;
					regfile(p, q, srchbuf.name, 
					        dos2unix((struct ftime *)&(srchbuf.wr_time)));
				}
			}
		}
		done = _dos_findnext(&srchbuf);
	}
	return cnt;							/* number of registed files */
}

/*******************************
	make file lists to append
*******************************/
void mklist(void)
{
	char far *p;
	char *q, *r;
	int cnt, Nfile;
	struct pat far *pt;
	char fname[13];

	Nfile = 0;
	init_regfile();
	for (pt = pbuf -> nxt; pt != NULL; pt = pt -> nxt) {
		p = pt -> pname;
		r = work;
		if (p[1] == ':') {			/* if file name includes drive */
			far_strcpy(r, p);			/* ignore base directory */
			r += 2;						/* don't regist drive name */
		} else {
			if ((uchar)*p != DELIM) {
				r = (char *)far_stpcpy(r, pt -> bdir);
			} else if (*(pt -> bdir) && (pt -> bdir)[1] == ':') {
				far_strcpy(r, pt -> bdir);
				r += 2;
			}
			far_strcpy(r, p);
		}
		if ((q = strchr(work, '+')) != NULL) {
			strcpy(q, "*.*");
		}
		q = getfilename(work);
		if (flg_r == 1) {			/* /r+ mode */
			strcpy(fname, q);
			strcpy(q, "*.*");
			cnt = travel(work, r, fname);
		} else {
			if (flg_r == 2) {				/* /r2 mode */
				if (*q == '.')
					strcat(r, DELIMSTR "*.*");
			}
			cnt = travel(work, r, NULL);
		}
		Nfile += pt -> cnt = cnt;
	}
}

struct fb far *searchfile(char *path)
{
	struct fb far *fp;

	for (fp = fbuf; fp != NULL; fp = fp -> nxt) {
		if (far_strcmp(path, fp -> cpos) == 0){
			fp -> used = 1;
			return fp;
		}
	}
	return NULL;
}
