/* disklist.c - functions for maintaining lists of directories for disks */

#include <windows.h>
#include <stdio.h>
#include "support.h"
#include "disklist.h"

#define	MAX_DISKS	16
#define	MAX_DIRS	32

typedef struct
{
	int cDirs;
	char const * apszDir[MAX_DIRS];
}
Disk_t;

static Disk_t Disk[MAX_DISKS];

void OpenDiskList(void)
{
	int iDisk;

	for (iDisk = 0; iDisk < ElementCount(Disk); iDisk++)
		Disk->cDirs = 0;
}

static BOOL AddDirectoryEntry(int nDisk, char * const pszDirectory)
{
	BOOL fSuccess = FALSE;
	int iDisk = nDisk - 1;
	Disk_t * const pDisk = &Disk[iDisk];
	char const szStrip[] = " \t";
	char * pszStripped = StripBoth(pszDirectory, szStrip);

	if (*pszStripped == '\0')
	{
		fputs("Empty directory entry", stderr);
		goto Error;
	}

	if (pDisk->cDirs == ElementCount(pDisk->apszDir))
	{
		fprintf(stderr, "%d: Exceeds maximum disk count", pDisk->cDirs + 1);
		goto Error;
	}

	{
		int cchDir = ExpandEnvironmentStrings(pszStripped, NULL, 0);
		BOOL fExpand = (cchDir != 0);
		char * pszDir;

		if (cchDir == 0)
		{
			cchDir = strlen(pszStripped) + 1;	/* +1 for the \0. */
		}

		cchDir++;	/* We may add a slash at the end. */
		pszDir = malloc(cchDir);

		if (pszDir == NULL)
		{
			perror(NULL);
			goto Error;
		}

		if (fExpand)
			ExpandEnvironmentStrings(pszStripped, pszDir, cchDir);
		else
			strcpy(pszDir, pszStripped);

		if (pszDir[strlen(pszDir) - 1] != '\\')
			strcat(pszDir, "\\");

		pDisk->apszDir[pDisk->cDirs++] = pszDir;
	}

	fSuccess = TRUE;

Error:

	return fSuccess;
}

BOOL AddDiskEntry(int nDisk, char * const pszDirectories)
{
	BOOL fSuccess = FALSE;
	char * pszDir;

	if (nDisk > ElementCount(Disk))
	{
		fprintf(stderr, "%d: Exceeds maximum disk count", nDisk);
		goto Error;
	}

	pszDir = strtok(pszDirectories, ";");
	while (pszDir)
		if (!AddDirectoryEntry(nDisk, pszDir))
			goto Error;
		else
			pszDir = strtok(NULL, ";");

	fSuccess = TRUE;

Error:

	return fSuccess;
}

char const * GetDirectory(int nDisk, char const * const pszLastDirectory)
{
	static char const * const pszDefault = ".\\";
	char const * pszResult;
	int iDisk = nDisk - 1;

	if (pszLastDirectory == pszDefault)
		pszResult = NULL;
	else if (iDisk > ElementCount(Disk) || Disk[iDisk].cDirs == 0)
		pszResult = pszDefault;
	else if (pszLastDirectory == NULL)
		pszResult = Disk[iDisk].apszDir[0];
	else
	{
		Disk_t * const pDisk = &Disk[iDisk];
		int iDir;

		for (iDir = 0; iDir < pDisk->cDirs; iDir++)
			if (pszLastDirectory == pDisk->apszDir[iDir])
				break;

		pszResult = (++iDir >= pDisk->cDirs) ? pszDefault : pDisk->apszDir[iDir];
	}

	return pszResult;
}

void CloseDiskList(void)
{
	int iDisk, iDir;

	for (iDisk = 0; iDisk < ElementCount(Disk); iDisk++)
		for (iDir = 0; iDir < Disk[iDisk].cDirs; iDir++)
			free((void *) Disk[iDisk].apszDir[iDir]);
}
