/*
    DELTREE v1.0 Copyright (C) Kai-Hong Chen 2003

    Support long file names when LFN API is found. 
    Work in DOS box, or pure DOS with long file name driver.
    * DosLfn v0.32n and LFNDOS v1.06 is tested.

    History:

    V1.0
     - The first version
*/

#parsecommandline TRUE
#define _USELONGNAME_ TRUE
#define _CHECKLONGNAMESUPPORT_ TRUE
#include "String.hmm"
#include "fprint.h--"
#include "dos.h--"
#include "write.h--"

byte opt_yes = 0,opt_test = 0;
dword total_dirs = 0,total_files = 0;

:void fastcall writeln()
{
	@putch(0Dh);
	@putch(0Ah);
}

:char fastcall choice(CX)
{
	DX = 0;

	for(;;)
	{
		@GETCH();
		IF(AL == 0Dh) && (DL != 0) BREAK;
		IF(AL >= 'a') && (AL <= 'z') AL -= 20h;
		DL = AL;
		IF(STRRCHR(CX,AL) == 0)
		{
			DL = 0;
		}
		ELSE
		{
			IF(DH)
			{
				@putch('\b');
				DH = 0;
			}
			@putch(DL);
			DH = 1;
		}
	}
	@writeln();
	return DL;
}

byte message[] =	"DELTREE v1.0 Copyright (C) Kai-Hong Chen 2003\n"
					"Deletes a directory and all subdirectories in it\n\n"
					"Usage: DELTREE path [path] ...\n"
					"  path        Files or directories you want to delete\n\n"

					"  /Y          Always answer YES to questions\n"
					"  /N          Never use long file name API\n"
					"  /T          Process a TEST to show information only\n\n"

					"Long file name API state : ";

int main()
{
	word fileargc = 0,i;
	byte *fileargv[255];
	byte *args;
	char dest_pathname[MAXPATH];
	char pathname[MAXPATH];
	byte opt_help = 0,one_by_one;
	FFBLK ffblk;

	@initLongnameApi();

    for(DX = 0;@PARAMCOUNT() > DX;DX++)
    {
        SI = @PARAMSTR(DX);
        IF(DSBYTE[SI] == '/')
        {
            SWITCH(DSBYTE[SI + 1])
            {
			CASE 'N':
			CASE 'n':
				longnameApi = 0;
				BREAK;
			CASE 'Y':
			CASE 'y':
				opt_yes++;
				BREAK;
			CASE 't':
			CASE 'T':
				opt_test++;
				BREAK;
            CASE '?':
            CASE 'h':
            CASE 'H':
                opt_help++;
                BREAK;
            default:
                printf("Invalid switch -  %s\n", SI);
                EXIT(1);
            }
        }
        ELSE
        {
            CX = SI;
            fileargv[fileargc] = CX;
            fileargc++;
        }
    }

    IF(opt_help) || (fileargc < 1)
    {
        printf(#message);
		IF(@isLongnameSupport()) printf("OK\n");
		ELSE  printf("disabled\n");
        EXIT(0);
    }

	for(i = 0;i < fileargc;i++)
	{
		one_by_one = 0;

		args = fileargv[i];
		truename(args,#dest_pathname);
		IF(CARRYFLAG) continue;

		truename(".",#pathname);
		CX = STRLEN(#dest_pathname);

		IF(dest_pathname[CX - 1] == '\\')
		{
			one_by_one++;
			dest_pathname[CX - 1] = 0;
		}

		CX = STRLEN(args);
		IF(DSBYTE[args + CX - 1] == '.') || (CX == 2) && (DSBYTE[args + 1] == ':')
		{
			one_by_one++;
		}

		IF(one_by_one)
		{
			STRCPY(#pathname,#dest_pathname);
			STRCAT(#pathname, "\\*.*");

			CX = FA_DIREC + FA_HIDDEN + FA_SYSTEM;
			IF(findfirst(#pathname,#ffblk,CX) == 0)
			do
			{
				IF(DSBYTE[#ffblk.ff_name] == '.') CONTINUE;

				STRCPY(#pathname,#dest_pathname);
				STRCAT(#pathname,"\\");
				STRCAT(#pathname,#ffblk.ff_name);
				deletePath(#pathname);

			} while(findnext(#ffblk) == 0);
			findclose();
		}
		ELSE deletePath(#dest_pathname);
	}

	IF(total_dirs | total_files)
	{
		printf("\nDeleted directories: ");
		WRITEDWORD(dword total_dirs);
		printf("\nDeleted files: ");
		WRITEDWORD(dword total_files);

		IF(opt_test) printf("\n\nTest Mode: No file or directory is really deleted\n");
	}
}

void deletePath(char *path)
{
	FFBLK ffblk;

	findfirst(path,#ffblk,FA_DIREC + FA_HIDDEN + FA_SYSTEM);
	$push ax
	findclose();
	$pop ax
	IF(AX != 0) return;

	STRCPY(STRRCHR(path,'\\') + 1,#ffblk.ff_name);

	IF(!opt_yes)
	{
		IF($test ffblk.ff_attrib,FA_DIREC)
			cprintf("Delete directory \"%s\" and all its subdirectories? [YNQ] ",path);
		ELSE
			cprintf("Delete file \"%s\"? [YNQ] ",path);
	}
	ELSE GOTO YESTODELETE;

	switch(choice("YNQ"))
	{
		CASE 'Y':
			YESTODELETE:
			printf("Deleting %s ...\n",path);
			IF($test ffblk.ff_attrib,FA_DIREC) 
			{
				deleteDirectory(path);
			}
			ELSE
			{
				IF(!opt_test)
				{
					IF($test ffblk.ff_attrib,FA_SYSTEM | FA_RDONLY) setfattr(path,0);
					deletefile(path);
				}
				total_files++;
			}
			BREAK;
		CASE 'N':
			RETURN;
		CASE 'Q':
			EXIT(0);
	}
}

void deleteDirectory(char *startDir)
{
	FFBLK ffblk;
	char pathname[MAXPATH];

	STRCPY(#pathname, startDir);
	STRCAT(#pathname, "\\*.*");

	CX = FA_DIREC + FA_HIDDEN + FA_SYSTEM;
    if(findfirst(#pathname,#ffblk,CX) == 0)
    do
    {
		IF(DSBYTE[#ffblk.ff_name] == '.') CONTINUE;

		STRCPY(#pathname, startDir);
		STRCAT(#pathname, "\\");
		STRCAT(#pathname, #ffblk.ff_name);

		IF($test ffblk.ff_attrib,FA_DIREC) deleteDirectory(#pathname);
		ELSE
		{
			IF(!opt_test)
			{
				IF($test ffblk.ff_attrib,FA_SYSTEM | FA_RDONLY) setfattr(#pathname,0);
				deletefile(#pathname);
			}
			total_files++;
		}

    } while(findnext(#ffblk) == 0);
	findclose();

	IF(!opt_test) rmdir(startDir);
	total_dirs++;
}