#include	"tree.h"
#include	"treefunc.h"

/***************************************************************************/
/*** メモリ確保/開放 ****/
mem_err()
{	fputs("メモリ不足で処理できません.\n",stderr);
	exit(1);
}
void *xmalloc( size_t size )
{	
	void	*p=malloc( size );
	
	if( p==NULLP )	mem_err();
	return p;
}
void far *fmalloc( u_long size )
{
	void far	*p=farmalloc(size);
	
	if( p==NULLP )	mem_err();
	return p;
}
/*
Tree	*FreeTree( tree )
Tree	*tree;
{
	if( tree!=NULLP )
	{
		tree->left = FreeTree( tree->left  );
		tree->right= FreeTree( tree->right );
		
		farfree( tree );
	}
	return NULLP;
}
*/

/***************************************************************************/
/*** 数の表示 ***/
putcn( c,n )
char	c;
int 	n;
{
	for( ; n>0 ; n--)	putchar(c);
}
putnum(n)
u_long	n;
{
	if( n>=1000)
	{	putnum( n/1000 );putchar(',');
		n %= 1000;
		if( n<100 )	putchar('0');
		if( n<10  )	putchar('0');
	}
	if( n>= 10 )	putnum( n/10   );
	
	putchar( n % 10 + '0');
}
putnumn(n,w)	/* 負数は知らない:-p */
u_long	n;
int 	w;
{
	u_long	i;
	
	if( n==0 )	w--;
	for( i=n     ; i>0; i/=10  )	w--;
	for( i=n/1000; i>0 ; i/=1000)	w--;
	putcn( ' ',w );
	
	putnum(n);
}

/***************************************************************************/
/*** パスとファイル名を連結 ***/
mk_FilePath(s,path,name)
char	far *s,far *path,far *name;
{
	char	far *p,far *pp;
	
	for( p=s,pp=path ; *pp!=NULLP ; p++,pp++)
		*p = *pp;
	if( s!=p && p[-1]!='\\' )	*p++ = '\\';	/* path\\ */
	
	for( pp=name ; *pp!=NULLP ; p++,pp++)
		*p = *pp;
	if( s!=p && p[-1]!='\\' )	*p++ = '\\';	/* path\\name\\ */
	
	*p = NULLP;
	
	/* name,pathが共にNULLであったときは、NULLとなる */
}

/** パスからファイル名のみ取り出す **/
char	*get_name(path)
char	*path;
{	char	*p=path;
	while( *p!=NULLP )	p++;
	while( p != path && *p != '\\' && *p!='/' && *p != ':' )	p--;
	
	if( *p=='\\' || *p=='/' || *p==':' )	++p;
	return p;
}

/***************************************************************************/
/*** ディスク残量を得る ***/
unsigned getDiskFree( dspace,path )
struct diskfree_t	*dspace;
char	*path;
{
	unsigned	drv;
	
	if( *path == NULLP )
		drv = 0;
	else if( *(path+1)==':' )
		drv = (*path>='a' ? *path-'a' : *path-'A')+ 1 ;
	
	return _dos_getdiskfree( drv, dspace );
}

long	allfiles=0;
long	allsize =0;

PutAllSize(tmp)
char	*tmp;
{	struct diskfree_t	dspace;
	
	/* 使用容量の総計を表示 */
	#define	POS	18
	putnumn( allfiles,POS ),puts(" 個のファイルがあります.");
	putnumn( allsize ,POS ),puts(" バイト使用しています.");
	
	if(!getDiskFree( &dspace, tmp ))
	{	
		putnumn( (long)( dspace.bytes_per_sector
						 * dspace.sectors_per_cluster
						  * dspace.avail_clusters )		,POS );
		puts(" バイトが使用可能です.");
	}
}

PutVolumeLabel(tmp)
char	*tmp;
{
	find_t	buf;
	int 	i;
	
	/* ボリュームラベルの表示 */
	tmp[3] = '*';
	tmp[4] = '.';
	tmp[5] = '*';
	tmp[6] = NULLP;
	if( _dos_findfirst( tmp, _A_VOLID ,&buf )==0 && buf.name!=NULLP )
	{
		putsn( "ボリュームラベル   : ");
		for( i=0; buf.name[i]!=NULLP ;i++ )
		{	if( buf.name[i]=='.' )	continue;
			putchar( buf.name[i] );
		}
		puts("\n");		/* 改行2つ */
	}
}

/***************************************************************************/

#if	0

/** 絶対パスの取得 **/
int 	get_absolute_pathname( buf,path )
char	*buf,*path;
{
	union REGS		regs,ret;
	struct SREGS	sregs;
	
	regs.h.ah = 0x60;
	regs.x.si = FP_OFF(path);
	regs.x.di = FP_OFF(buf);
	sregs.ds = FP_SEG((char far *)path);
	sregs.es = FP_SEG((char far *)buf);
	
	intdosx(&regs, &ret, &sregs );
	
	return ret.x.cflag;
}
conv_slash( str )
char	*str;
{
	char	*p;
	
	for( p=str; *p!=NULLP ; p++ )
	{
		if( iskanji(*p) )	p++;
		else if( *p == '/')	*p='\\';
	}
}

get_fullpathname( ret,path )
char	*ret,*path;
{
	int 	i;
	
	conv_slash( path );
	
	i=strlen( path );
	if( i==0 || path[i-1]!='.' )
		strcat( path,"." );	/* カレントを明示的に示す必要あり */
	
	i=get_absolute_pathname( ret,path );
	
	/* CD-ROMは "\\Q.\A." がルートを指すので不要な部分は切り取る */
	chk_networkdrv(ret);
	/* 他のデバイスだとどうなるのだろ、この処理怪しいぞ */
	
	if( i && access(ret,0) )
	{	errputs( "パスが存在しません\n" );
		exit(1);
	}
	
}
#endif

/** フルパス名の取得 **/
/* 相対パスで指定されたときの処理が面倒なので */
/* カレントを得るついでにchdirしてみる(^^;)   */

int get_fullpathname( ret, path )
char	*ret,*path;
{
	char		*cur,*drv,*pp=path;
	char		tmp[4];
	int 		i;
	unsigned	lastdrv;
	
	*ret=NULLP;
	
	/* カレント保存 */
	drv=getcwd(NULLP,FILENAME_MAX);
	
	for( i=0; path[i]!=NULLP ;i++ )
	{
#if 0	/* 先に調べてあるはずなので省略 */
		if( path[i]=='/' )
			path[i]='\\';
		else
#endif
		if( i==1 && path[i]==':' )
		{
/* chdir だけで調べられる */
#if 0
			unsigned	drvno;
			/* 指定のドライブは存在しているか? */
			_dos_setdrive( tolower(*path)-'a'+1 ,&lastdrv );
			_dos_getdrive( &drvno );
			_dos_setdrive( tolower(*drv )-'a'+1, &lastdrv);
			
			if( drvno != tolower(*path)-'a'+1 )	/* ドライブ移動に失敗! */
				goto patherr;
#endif
			/* 使用可能な状態にあるか? */
			*tmp    = *path;		/* chdir @:. */
			*(tmp+1)= ':';
			*(tmp+2)= '.';
			*(tmp+3)= NULLP;
			if( chdir( tmp ) )		/* カレントディレクトリがない! */
				goto patherr;
			
			_dos_setdrive( tolower(*path)-'a'+1 ,&lastdrv );
			pp += 2;
		}
	}
	if( i>1 && path[i-1]=='\\' && path+i-1 != pp )
		path[i-1]=NULLP;	/* 末尾の '\\' は消す */
	
	
	cur=getcwd( NULLP, FILENAME_MAX );	/* パスの保存 */
	
	/* 実際にchdirしてみてカレントパスを得る */
	i=0;
	if( *pp!=NULLP )
		i=chdir( pp );
	getcwd( ret, FILENAME_MAX );
	
	chdir( cur );						/* パスの復旧 */
	
	
	/** カレント復旧 **/
	_dos_setdrive( tolower(*drv )-'a'+1, &lastdrv);
	
patherr:
	free(drv);
	free(cur);
	
	if( i || ret==NULLP )
	{	errputs( "パスが存在しません\n" );
		exit(1);
	}
	
	return 0;
}

