/*****************************************************************************/

#include <stdio.h>
#include <doslib.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <iocslib.h>
#include "defines.h"
#include "fat32.h"
#include "adisk.h"
#include "astdio.h"
#include "astring.h"
#include "aparam.h"
#include "akey.h"
#include "acmp.h"
#include "amacro.h"

char prog[]="@@> TREE32.C : 2000/12/05 TUE : COMMAND : TREE32 : X680x0 : GCC";

// 2000/09/14 FAT32対応版
//		削除	英大文字小文字区別、ファイル名長さ指定
//			物理ドライブ指定
// 2000/10/19 ファイル名長定数をfat32.hのそれに合わせて変更
// 2000/12/05 FILE32のサイズが大きくなりスタックをオーバーする可能性が出てきたのでmalloc()
//	      による確保に変更した
//	      表示の２ルーチンを統一(ptree/ptree2)
/*****************************************************************************/
/* グローバル変数 */

int attr,modef; /* modef:変数名fmodeは使えないので */
int fchar,fkbclr;

#define	DIRLEN	(MAXSHORTFILEEXT)

/*****************************************************************************/

void kb()
/* キーボードバッファークリア＆表示速度設定 */
{
	if (fkbclr) kbclr();
	if (fchar) kslow();
}

/*****************************************************************************/

void set_color(int fatrb)
/* 属性別表示色設定 */
{
int c=TWHITE; /* 白 */
	if (fatrb & FA_RONLY) c=TCYAN;  /* 水色 */
	if (fatrb & FA_HIDE) c|=HLIGHT; /* ハイライト */
	if (fatrb & FA_SYS) c|=REVERSE; /* リバース */
	B_COLOR(c);
}

/*****************************************************************************/

void print_vol(unchar *name)
/* ボリューム名表示（ショート）*/
{
static unchar drv[MAXDRIVE32],dir[MAXDIR32],fname[MAXPATH32],ext[MAXEXT32];
static FILE32 fp;
	strsfn32(name,drv,dir,fname,ext);
	strcpy(fname,drv);
	strcat(fname,"\\*.*");
	if (FILES32(&fp,fname,FA_VOL)<0) prints("ボリューム名無し");
	else prints(fp.name);
	crlf();
	if (fkbclr) kbclr();
	if (fchar) kslow();
}

/*****************************************************************************/

int ptree(int x,unchar *dir,int hyou)
/* modef<>0 のときはファイルも表示する */
/* modef==2 のときはファイル属性毎に色を変える */
// hyou=0 : 標準モード / 1=拡大モード
/* 標準表示モード */
/* (x*4,csrlin())の座標からdirで示されるディレクトリーの内容を表示する */
/* 拡大表示モード */
/* (x,csrlin())の座標からdirで示されるディレクトリーの内容を表示する */
/* リターン値は表示数 */
{
#define SEP "|   "
#if 0
FILE32 fp;
unchar path[MAXPATH32];
#else
unchar *work;
FILE32 *fp;
unchar *path;
#endif
int fatrb,xx,px,i,first=1;
int count=0;
	// ワークエリアの動的確保
	// スタック不足を回避するため
	work=malloc(sizeof(FILE32)+MAXPATH32);
	if (work==NULL) {
		prints("ワークエリアが確保出来ません\n");
		exit(55);
	}
	fp=(FILE32 *)work;
	path=&work[sizeof(FILE32)];
	
	strcpy(path,dir);
	strcat(path,"*.*");
	if (FILES32(fp,path,attr)<0) goto TREE_END;
	do {
		if (CheckParentDir(fp->name)) continue; /* '.' '..' = direcrory */
		
		if (hyou) {
			xx=x/DIRLEN;
			if (!first) for(i=0;i<xx;i++) printss("|",kstring(DIRLEN-1," "));
			first=0;
		} else {
			printss(kstring(x,SEP),"|-");
		}
		
		/* file/directory name print */
		fatrb=fp->atr;
		if (modef==2) set_color(fatrb);
		if (hyou) {
			printss("|-",fp->name);
		} else {
			prints(fp->name); crlf();
			count++;
		}
		if (modef==2) B_COLOR(TWHITE); /* 白 */
		
		if (fatrb & FA_DIREC) {
			unchar direc[MAXDIR32];
			strcpy(direc,dir);
			strcat(direc,fp->name);
			strcat(direc,"\\");
			if (hyou) {
				px=1+strlen(fp->name); /* |-fname */
				if (!first) px+=(x/DIRLEN)*DIRLEN; /* |" " */
				xx=((px/DIRLEN)+1)*DIRLEN-px;
				prints(kstring(xx-1,"-"));
				ptree(px+xx,direc,hyou);
				for(i=0;i<=(x/DIRLEN);i++) printss("|",kstring(DIRLEN-1," "));
			} else {
				if (ptree(x+1,direc,hyou)>0) printsn(kstring(x,SEP),"|");
			}
		}
		if (hyou) crlf();
		kb(); /* １行毎にキーボードバッファークリア */
	} while (NFILES32(fp)>=0);
TREE_END:
	if (hyou) {
		if (first) crlf(); /* no file in this directory */
	}
	free(work);
	return(count);
}

/*****************************************************************************/

void main(int argc,unchar *argv[])
{
int i,ftree,fvol,helpflag=0;
unchar name[MAXPATH32];
	/* オプションチェック初期化 */
	clear_param();
    HELP:
	if (helpcom(argc,argv,helpflag,"TREE32","[Option] FAT32パス名")) exit(255);
	
	/* parameter check */
	/* /! = key board buffer clear mode */
	fkbclr=check_param2("!",argv,argc,0);
	
	/* ファイル名も表示するモード */
	modef=0;
	attr=FA_DIREC;
	i=check_param2("F",argv,argc,BIT0);
	if (i) {
		modef=1+(toupper(argv[i][2])=='C'); /* /FC=color mode */
		attr|=(FA_ARCH|FA_RONLY|FA_HIDE|FA_SYS);
	}
	
	/* ボリューム名表示モード */
	fvol=check_param2("V",argv,argc,BIT0);
	
	/* 拡大表示モード */
	ftree=check_param2("T",argv,argc,BIT0);
	
	/* オプションチェック */
	i=check_param_error(argv,argc);
	if (i) {
		printsn("\aオプションエラーです：",argv[i]);
		exit(3);
	}
	
	/* "/"または"-"のついていない最初のパラメーターがpathnameになる */
	name[0]=0; /* pathnameがないとき */
	i=getfname(argc,argv,1,NULL);
	if (i==0) {
		/* help! */
		helpflag=100;
		goto HELP;
	}
	
	/* ディレクトリ名にも拡張子を付けることが出来るから */
	strmfp30(name,"",argv[i],"");
	#if 0
	strcpy(name,argv[i]);
	strcat(name,"\\");
	#endif
	
	/* 出力先がキャラクターデバイスかどうか */
	fchar=check_char_device(stdout);
	
	/* ボリューム名表示 */
	if (fvol) print_vol(name);
	
	if (ftree) { /* 拡大表示モード */
		printc('['); printsn(name,"]");
		ptree(0,name,1);
	} else { /* 標準モード */
		if (name[0]!=0) {
			prints(name); crlf();
		}
		if (ptree(0,name,0)==0) prints("|\n");
	}
	exit(0);
}

/*****************************************************************************/
