/* << MSC V5.1 >> [FM-TOWNS] ************************************************
*
*	ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ情報取得(MS-DOS汎用)
*	----------------------------------------------------------------------
*	All Rights Reserved, Copyright (C) Y.Hirata 1993.
*	Programmed by Y.Hirata ( NIFTY-ID: NAB03321  パオパオ )
*
*	NOTE: TAB=4
****************************************************************************/

#include <stdio.h>			/*  printf,putchar	*/
#include <stdlib.h>			/*  exit		*/
#include <string.h>			/*  str*		*/
#include <direct.h>			/*  getcwd		*/
#include <conio.h>			/*  getch		*/

#include "lib\define.h"		/*  定数宣言	*/
#include "lib\typedef.h"	/*  型宣言		*/
#include "lib\mem.h"		/*  _peek		*/
#include "lib\dirlib.h"		/*  <dos.h>,_aread	*/
#include "lib\doscall.h"	/*  <dos.h>,_getDPB	*/

#define	isroot(s)			((s)[1]==':' && (s)[2]=='\\' && (s)[3]=='\0')

_DPB	_dpb ;									/*  DPB情報				*/
int		FATbit ;								/*  FATﾋﾞｯﾄｻｲｽﾞ			*/

typedef struct {
	BYTE	name[8] ;		/*  ﾌｧｲﾙ名			*/
	BYTE	ext[3] ;		/*  拡張子			*/
	BYTE	attr ;			/*  属性			*/
	BYTE	res[10] ;		/*  ﾘｻﾞｰﾌﾞ			*/
	WORD	time ;			/*  作成時刻		*/
	WORD	date ;			/*  作成日付		*/
	WORD	entry ;			/*  FATｴﾝﾄﾘ			*/
	DWORD	size ;			/*  ﾌｧｲﾙｻｲｽﾞ		*/
} DIR_ENTRY ;

#define	ENTRYSIZE			(sizeof( DIR_ENTRY ))
#define	FATBUFSIZE			8192				/*  FAT用領域ｻｲｽﾞ		*/
#define	FATSECTOR			(FATBUFSIZE / _dpb.bps)

#define	ROOTSCT				(_dpb.rde * ENTRYSIZE / _dpb.bps)
#define	DIRENTpS			(_dpb.bps / ENTRYSIZE)
#define	DIRENTpC			(DIRENTpS * (_dpb.spc+1))

unsigned	_cdrv ;								/*  ｶﾚﾝﾄﾄﾞﾗｲﾌﾞ			*/
char		*_cdir ;							/*  ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ			*/
char		_abspath[128] ;						/*  物理ﾊﾟｽ名			*/
BYTE		*_fat ;								/*  FATﾃｰﾌﾞﾙ領域		*/
DWORD		_fatss ;							/*  開始ｾｸﾀ番号			*/
DIR_ENTRY	*_direntry ;						/*  ﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ			*/
WORD		_maxentry ;							/*  最大FATｴﾝﾄﾘ			*/
WORD		_nentry ;							/*  有効ｴﾝﾄﾘ数			*/
WORD		_dentry ;							/*  削除ｴﾝﾄﾘ数			*/

#define	LINEpPAGE			24					/*  1画面の行数			*/
int			_linecnt ;							/*  表示行数			*/

struct {
	unsigned	critical:1 ;	/*  致命的ｴﾗｰ発生ﾌﾗｸﾞ	*/
	unsigned	rootdir:1 ;		/*  ﾙｰﾄﾃﾞｨﾚｸﾄﾘ識別ﾌﾗｸﾞ	*/
	unsigned	fat:1 ;			/*  FAT読み込み済ﾌﾗｸﾞ	*/
	unsigned	sct32:1 ;		/*  32bitｾｸﾀｻﾎﾟｰﾄﾌﾗｸﾞ	*/
} _flg ;										/*  処理ﾌﾗｸﾞ			*/

struct {
	unsigned	color:1 ;	/*  色付表示				*/
	unsigned	dinf:1 ;	/*  ﾄﾞﾗｲﾌﾞ情報表示			*/
	unsigned	sector:1 ;	/*  ﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘのｾｸﾀ表示	*/
	unsigned	page:1 ;	/*  ﾍﾟｰｼﾞ制御				*/
} _optsw ;										/*  ｵﾌﾟｼｮﾝｽｲｯﾁ			*/

void putcrlf( void )
/*===========================================================================
*	改行表示
===========================================================================*/
{
	putchar( '\n' ) ;
	if ( !_optsw.page ) return ;
	if ( ++_linecnt > LINEpPAGE-2 ) {
		printf( "--- more ---" ) ;
		getch() ;
		putchar( '\n' ) ;
		_linecnt=0 ;
	}
}

void getDPB( void )
/*===========================================================================
*	DPB情報取得
===========================================================================*/
{
	WORD	attr ;

	_getDPB( _cdrv,&_dpb ) ;
	if ( _dpb.maxclst < 0x0FF7 ) {
		FATbit  = 12 ;							/*  12bit FAT		*/
		_maxentry = 0x0FF7 ;
	} else {
		FATbit  = 16 ;							/*  16bit FAT		*/
		_maxentry = 0xFFF7 ;
	}
	if ( _osmajor >= 10 ) {						/*  OS/2互換BOX		*/
		_flg.sct32 = 1 ;
		return ;
	}
	attr = (WORD)_peek( _dpb.dseg,_dpb.doff+4 ) ;
	_flg.sct32 = ( attr & 0x0002 ) ? 1 : 0 ;	/*  32bitｾｸﾀｻﾎﾟｰﾄ?	*/
}

int absRead( WORD nsct,DWORD sctno,void *buf )
/*===========================================================================
*	物理読み込み
*	< IN  >	: nsct	読み込みｾｸﾀ数
*			: sctno	読み込み開始ｾｸﾀ番号
*			: buf	ﾃﾞｰﾀ格納先ｱﾄﾞﾚｽ
*	< OUT >	: buf	読み込んだﾃﾞｰﾀ
*	< RET >	: 下位ﾊﾞｲﾄにｴﾗｰｺｰﾄﾞを返す. (上位ﾊﾞｲﾄ=00h:正常終了, =01h:ｴﾗｰ発生)
*				=00h	書き込み禁止である
*				=01h	ﾕﾆｯﾄが存在しない
*				=02h	ﾄﾞﾗｲﾌﾞの準備ができていない
*				=03h	存在しないｺﾏﾝﾄﾞである
*				=04h	ﾃﾞｰﾀのCRCｴﾗｰ
*				=05h	ﾊﾞｯﾄﾞﾄﾞﾗｲﾌﾞﾘｸｴｽﾄｽﾄﾗｸﾁｬの長さ
*				=06h	ｼｰｸｴﾗｰ
*				=07h	存在しないﾒﾃﾞｨｱﾀｲﾌﾟである
*				=08h	ｾｸﾀが存在しない
*				=09h	ﾌﾟﾘﾝﾀの用紙切れ
*				=0Ah	書き込み不良
*				=0Bh	読み込み不良
*				=0Ch	一般的なﾃﾞｨｽｸ不良
*				=0Fh	不正なﾒﾃﾞｨｱ交換があった
===========================================================================*/
{
	struct {
		DWORD	sctno ;							/*  32bitｾｸﾀ番号		*/
		WORD	nsct ;							/*  R/Wｾｸﾀ数			*/
		WORD	off ;							/*  ﾊﾞｯﾌｧｵﾌｾｯﾄ			*/
		WORD	seg ;							/*  ﾊﾞｯﾌｧｾｸﾞﾒﾝﾄ			*/
	} packet ;

	if ( _flg.sct32 ) {							/*  32bitｾｸﾀｻﾎﾟｰﾄ		*/
		packet.sctno = sctno ;
		packet.nsct  = nsct ;
		packet.off   = _off( buf ) ;
		packet.seg   = _seg( buf ) ;
		return _aread( _cdrv-1,-1,-1,&packet ) ;
	}
	return _aread( _cdrv-1,nsct,(WORD)sctno,buf ) ;
}

DWORD tosector( WORD cluster )
/*===========================================================================
*	ｸﾗｽﾀ値→論理ｾｸﾀ番号 (ｻﾌﾞﾃﾞｨﾚｸﾄﾘ時)
===========================================================================*/
{
	DWORD	sector ;

	cluster -= 2 ;
	sector = (DWORD)cluster ;
	sector <<= _dpb.scnt ;
	sector += (DWORD)_dpb.fds ;
	return sector ;
}

int fatRead( DWORD *off )
/*===========================================================================
*	FAT読み込み済かどうかのﾁｪｯｸ
*	< RET >	: ｴﾗｺｰﾄﾞを返す.
*				=0	正常終了
*				=1	ｾｸﾀ読み込み失敗
===========================================================================*/
{
	DWORD	sp, ep, fsector ;
	int		ret ;

	sp = _fatss * (DWORD)_dpb.bps ;
	ep = (DWORD)( FATSECTOR * _dpb.bps ) ;		/*  FATﾊﾞｯﾌｧｻｲｽﾞ		*/
	ep = sp + ep - 2L ;							/*  WORD読み込みのため	*/
	if ( *off < sp || *off > ep || !_flg.fat ) {	/*  FAT読み込み		*/
		_fatss  = *off / (DWORD)_dpb.bps ;
		fsector = (DWORD)_dpb.res + _fatss ;
		ret = absRead( FATSECTOR,fsector,_fat ) ;
		if ( ret ) {
			printf( "\aFATの読み込みに失敗しました." ) ;
			printf( " (ｾｸﾀNo.%08lX〜%uｾｸﾀ分, error code: %02Xh)",
											fsector,FATSECTOR,_lo(ret) ) ;
			putcrlf() ;
			return 1 ;
		}
		sp = _fatss * (DWORD)_dpb.bps ;
		_flg.fat = 1 ;
	}
	*off -= sp ;								/*  現ﾊﾞｯﾌｧ中のｵﾌｾｯﾄ	*/
	return 0 ;
}

int nextcluster( WORD *cluster )
/*===========================================================================
*	次のｸﾗｽﾀ取得
*	< RET >	: ｴﾗｺｰﾄﾞを返す.
*				=0	正常終了
*				=1	ｾｸﾀ読み込み失敗
===========================================================================*/
{
	WORD	next, clst ;
	DWORD	nextp ;

	clst = *cluster ;
	if ( FATbit == 12 ) {						/*  12bit FAT			*/
		nextp = (DWORD)clst + (DWORD)( clst >> 1 ) ;		/*  ×1.5	*/
		if ( fatRead( &nextp ) ) return 1 ;
		next = (WORD)nextp ;
		next = _WORD( _fat + next ) ;
		clst = ( clst & 1 ? ( next >> 4 ) : ( next & 0x0FFF ) ) ;
	} else {									/*  16bit FAT			*/
		nextp = (DWORD)clst + (DWORD)clst ;					/*  ×2		*/
		if ( fatRead( &nextp ) ) return 1 ;
		next = (WORD)nextp ;
		clst = _WORD( _fat + next ) ;
	}
	*cluster = clst ;
	return 0 ;
}

void dispColor( int entry )
/*===========================================================================
*	表示色設定
===========================================================================*/
{
	if ( _direntry[entry].name[0] == 0x00 )				/*  空き		*/
		return ;
	else if ( _direntry[entry].name[0] == 0xE5 )		/*  削除		*/
		printf( "\x1b[31m" ) ;
	else if ( _direntry[entry].name[0] == 0x2E )		/*  ｻﾌﾞﾃﾞｨﾚｸﾄﾘ	*/
		printf( "\x1b[36m" ) ;
	else if ( _direntry[entry].attr & _A_SUBDIR )		/*  ｻﾌﾞﾃﾞｨﾚｸﾄﾘ	*/
		printf( "\x1b[36m" ) ;
	else if ( _direntry[entry].attr & _A_VOLID )		/*  ﾎﾞﾘｭｰﾑﾗﾍﾞﾙ	*/
		printf( "\x1b[33m" ) ;
	else if ( _direntry[entry].attr & _A_SYSTEM )		/*  ｼｽﾃﾑ		*/
		printf( "\x1b[32m" ) ;
	else if ( _direntry[entry].attr & _A_HIDDEN )		/*  隠し		*/
		printf( "\x1b[32m" ) ;
	else if ( _direntry[entry].attr & _A_RDONLY )		/*  書込禁止	*/
		printf( "\x1b[32m" ) ;
}

int dispFname( int entry )
/*===========================================================================
*	ﾌｧｲﾙ名表示
===========================================================================*/
{
	register int	cnt ;

	if ( _direntry[entry].name[0] == 0x00 ) return 1 ;	/*  空きｴﾝﾄﾘ	*/
	if ( _direntry[entry].name[0] == 0x05 ) {			/*  1byte目がE5	*/
		_nentry++ ;
		putchar( 0xE5 ) ;
	} else if ( _direntry[entry].name[0] == 0xE5 ) {	/*  削除ｴﾝﾄﾘ	*/
		_dentry++ ;
		putchar( '?' ) ;
	} else {											/*  通常ｴﾝﾄﾘ	*/
		_nentry++ ;
		putchar( _direntry[entry].name[0] ) ;
	}
	for ( cnt=1; cnt<8; cnt++ )
		putchar( _direntry[entry].name[cnt] ) ;			/*  ﾌｧｲﾙ名		*/
	putchar( ' ' ) ;
	for ( cnt=0; cnt<3; cnt++ )
		putchar( _direntry[entry].ext[cnt] ) ;			/*  拡張子		*/
	return 0 ;
}

void dispFattr( BYTE attr )
/*===========================================================================
*	ﾌｧｲﾙ属性表示
===========================================================================*/
{
	putchar( attr & _A_ARCH   ? 'a' : '-' ) ;
	putchar( attr & _A_SYSTEM ? 's' : '-' ) ;
	putchar( attr & _A_HIDDEN ? 'h' : '-' ) ;
	putchar( attr & _A_RDONLY ? 'o' : 'w' ) ;
}

void dispEntry( void )
/*===========================================================================
*	ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ情報表示
===========================================================================*/
{
	register int	entry ;

	for ( entry=0; entry<DIRENTpS; entry++ ) {
		if ( _optsw.color ) dispColor( entry ) ;
		if ( dispFname( entry ) ) continue ;
		if ( _direntry[entry].attr & _A_VOLID )
			printf( "  < VOL >" ) ;
		else if ( _direntry[entry].attr & _A_SUBDIR )
			printf( "  < DIR >" ) ;
		else
			printf( " %8ld",_direntry[entry].size ) ;
		printf( "  %02d-%02d-%02d  %2d:%02d:%02d  ",
			YEAR(_direntry[entry].date),MONTH(_direntry[entry].date),
			DATE(_direntry[entry].date),HOUR(_direntry[entry].time),
			MINUTE(_direntry[entry].time),SEC(_direntry[entry].time) ) ;
		dispFattr( _direntry[entry].attr ) ;
		printf( "  (cluster=%04X",_direntry[entry].entry ) ;
		if ( _direntry[entry].entry < 1 ) {
			;
		} else if ( _direntry[entry].entry < _maxentry ) {
			printf( ":sector=%08lX",tosector( _direntry[entry].entry ) ) ;
		} else if ( _direntry[entry].entry == _maxentry ) {
			printf( ":不良クラスタ" ) ;
		} else {
			printf( ":最終クラスタ" ) ;
		}
		printf( _optsw.color ? ")\x1b[m" : ")" ) ;
		putcrlf() ;
	}
}

int dispCdir( void )
/*===========================================================================
*	ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ表示
*	< RET >	: ｴﾗｺｰﾄﾞを返す.
*				=0	正常終了
*				=1	ｾｸﾀ読み込み失敗
*				=2	ﾌｧｲﾙが見つからない
===========================================================================*/
{
	register WORD	cnt ;
	struct find_t	dta ;
	unsigned	attr=(_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_SUBDIR|_A_ARCH) ;
	WORD	cluster ;
	DWORD	sector ;
	int		ret ;

	if ( _dos_findfirst( "*.*",attr,&dta ) && !_flg.rootdir ) return 2 ;
/*
*	最初の検索時に, ﾙｰﾄﾃﾞｨﾚｸﾄﾘでなければ '.' が見つかる筈である.
*	ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘのｴﾝﾄﾘは, '.' の指しているｸﾗｽﾀをﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘとして処理する.
*/
	_nentry = _dentry = 0 ;
	putcrlf() ;
	if ( _flg.rootdir ) {						/*  root directory		*/
		sector = (DWORD)_dpb.fsr ;
		for ( cnt=0; cnt<ROOTSCT; cnt++, sector++ ) {
			if ( _optsw.sector ) {
				printf( "< sector:%08lX >",sector ) ;
				putcrlf() ;
			}
			ret = absRead( 1,sector,_direntry ) ;
			if ( ret ) {
				printf( "_aread error : %02Xh",_lo(ret) ) ;
				putcrlf() ;
				return 1 ;
			}
			dispEntry() ;						/*  ﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ表示		*/
		}
	} else {									/*  sub directory		*/
		cluster = _WORD( (char *)&dta + 0x0F ) ;
		for ( ; cluster<_maxentry; ) {
			sector = tosector( cluster ) ;
			for ( cnt=0; cnt<_dpb.spc+1; cnt++, sector++ ) {
				if ( _optsw.sector ) {
					printf( "< sector:%08lX >",sector ) ;
					putcrlf() ;
				}
				ret = absRead( 1,sector,_direntry ) ;
				if ( ret ) {
					printf( "_aread error : %02Xh",_lo(ret) ) ;
					putcrlf() ;
					return 1 ;
				}
				dispEntry() ;					/*  ﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ表示		*/
			}
			if ( nextcluster( &cluster ) ) return 1 ;
		}
	}
	putcrlf() ;
	printf( "%6d 個の有効エントリがあります.",_nentry ) ;
	putcrlf() ;
	printf( "%6d 個の削除エントリがあります.",_dentry ) ;
	putcrlf() ;
	return 0 ;
}

void dispLabel( void )
/*===========================================================================
*	ﾎﾞﾘｭｰﾑﾗﾍﾞﾙ表示
===========================================================================*/
{
	register int	cp ;
	struct find_t	dta ;
	unsigned	attr=_A_VOLID ;
	int		findflg=0 ;

	if ( !_dos_findfirst( "\\*.*",attr,&dta ) ) {
		do {
			if ( dta.attrib & _A_VOLID ) findflg = 1 ;
		} while ( !_dos_findnext( &dta ) ) ;	/*  次のｴﾝﾄﾘ			*/
	}
	if ( findflg ) {
		for ( cp=0; cp<12; cp++ )
			if ( dta.name[cp] == '.' )
				strcpy( dta.name+cp,dta.name+cp+1 ) ;
		printf( " %s",dta.name ) ;
	} else {
		printf( "ありません." ) ;
	}
	putcrlf() ;
}

void dispDrvErr( void )
/*===========================================================================
*	ﾄﾞﾗｲﾌﾞ指定誤り表示
===========================================================================*/
{
	_flg.critical = 1 ;
	printf( "\a ドライブの指定が違います." ) ;
	putcrlf() ;
}

int dispCurrent( void )
/*===========================================================================
*	ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ表示
===========================================================================*/
{
	putcrlf() ;
	printf( " ドライブ %c: のディスクのボリュームラベルは",_cdrv+'@' ) ;
	dispLabel() ;
	if ( getabspath( _cdir,_abspath ) ) {		/*  物理ﾊﾟｽ名取得		*/
		dispDrvErr() ;
		return 1 ;
	}
	printf( " ディレクトリは %s",_cdir ) ;
	putcrlf() ;
	if ( isnetdrv( _cdrv ) ) {					/*  ﾘﾓｰﾄ				*/
		putcrlf() ;
		printf( "\a %c: はリモートドライブ",_cdrv+'@' ) ;
		printf( "(DOSによる物理アクセス不可)のため扱えません." ) ;
		putcrlf() ;
		return 1 ;
	}
	if ( isjoindrv( _cdrv ) || stricmp( _cdir,_abspath ) ) {
		putcrlf() ;
		printf( "\a このドライブは再割当されています." ) ;
		putcrlf() ;
		printf( "   物理パス名は %s",_abspath ) ;
		putcrlf() ;
	}
	return 0 ;
}

int init( void )
/*===========================================================================
*	初期処理
*	< RET >	: ｴﾗｺｰﾄﾞを返す.
*				=0	正常終了
*				=1	ｾｸﾀ読み込み失敗
*				=2	ﾒﾓﾘ不足(FAT領域)
*				=3	ﾒﾓﾘ不足(ﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ)
*				=4	物理ｱｸｾｽ不可
===========================================================================*/
{
	_flg.critical = 0 ;
	resetdisk() ;								/*  ﾘｾｯﾄﾃﾞｨｽｸ			*/
	_dos_getdrive( &_cdrv ) ;					/*  ｶﾚﾝﾄﾄﾞﾗｲﾌﾞ			*/
	_cdir = getcwd( NULL,_MAX_DIR ) ;			/*  ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ取得		*/
	if ( dispCurrent() ) return 4 ;				/*  ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ表示		*/
	_flg.rootdir = isroot( _abspath ) ;			/*  ﾙｰﾄﾃﾞｨﾚｸﾄﾘ識別		*/
	getDPB() ;									/*  DPB情報取得			*/
	_flg.fat = 0 ;
	_fat = NULL ;
	_direntry = NULL ;
	if ( !_flg.rootdir ) {						/*  ﾙｰﾄﾃﾞｨﾚｸﾄﾘでない時	*/
		if ( (_fat = (BYTE *)malloc( FATBUFSIZE )) == NULL ) {
			return 2 ;
		}
		_fatss = 0L ;
	}
	if ( (_direntry = (DIR_ENTRY *)malloc( _dpb.bps )) == NULL ) {
		if ( _fat != NULL ) free( _fat ) ;
		return 3 ;
	}
	return 0 ;
}

void dispDpb( void )
/*===========================================================================
*	ﾃﾞｨｽｸ情報表示
===========================================================================*/
{
	putcrlf() ;
	printf( "< %d bit FAT >",FATbit ) ;
	if ( _flg.sct32 ) printf( " ( 32bitセクタ番号サポート )" ) ;
	putcrlf() ;
	printf( "bytes/sector .................. %u",_dpb.bps ) ;
	putcrlf() ;
	printf( "sectors/cluster ............... %u",_dpb.spc+1 ) ;
	putcrlf() ;
	printf( "shift count ................... %d",_dpb.scnt ) ;
	putcrlf() ;
	printf( "reserved sectors .............. %u",_dpb.res ) ;
	putcrlf() ;
	printf( "sectors/FAT ................... %u",_dpb.spf ) ;
	putcrlf() ;
	printf( "first data sector ............. %04Xh",_dpb.fds ) ;
	putcrlf() ;
	printf( "first sector of root directry . %04Xh",_dpb.fsr ) ;
	putcrlf() ;
	printf( "directory entries/cluster ..... %u",DIRENTpC ) ;
	putcrlf() ;
	printf( _flg.rootdir ? "< root " : "< sub " ) ;
	printf( "directory >" ) ;
	putcrlf() ;
}

void dispSize( DWORD size )
/*===========================================================================
*	ｻｲｽﾞ表示
===========================================================================*/
{
	double	sizew ;

	sizew = (double)size ;
	if ( size < 1024L ) {						/*  1024未満			*/
		printf( "%10ld バイト               ",size ) ;
	} else if ( size < 1048576L ) {				/*  1024*1024未満		*/
		printf( "%10ld バイト (約 %6.1lf KB)",size,sizew/1024.0L ) ;
	} else {									/*  1024*1024以上		*/
		printf( "%10ld バイト (約 %6.1lf MB)",size,sizew/1048576.0L ) ;
	}
}

void dispDrive( void )
/*===========================================================================
*	ﾄﾞﾗｲﾌﾞ容量表示
===========================================================================*/
{
	struct diskfree_t	dinf ;
	DWORD	size ;
	double	pers ;
	int		cdrom ;

	putcrlf() ;
	if ( _dos_getdiskfree( 0,&dinf ) ) {		/*  ﾄﾞﾗｲﾌﾞ情報取得		*/
		dispDrvErr() ;
		return ;
	}
	cdrom = iscdrom( 0 ) ;

	/*	全ﾃﾞｨｽｸ容量
	---------------- */
	if ( !cdrom ) {								/*  通常ﾄﾞﾗｲﾌﾞ			*/
		size = (DWORD)dinf.total_clusters
			 * (DWORD)dinf.sectors_per_cluster
			 * (DWORD)dinf.bytes_per_sector ;
	} else {									/*  CD-ROM				*/
		size = 270000L
			 * (DWORD)dinf.sectors_per_cluster
			 * (DWORD)dinf.bytes_per_sector ;
	}
	printf( " 全ディスク容量   : " ) ;
	dispSize( size ) ;
	putcrlf() ;

	/*	使用ﾃﾞｨｽｸ容量
	------------------ */
	if ( !cdrom ) {								/*  通常ﾄﾞﾗｲﾌﾞ			*/
		size = (DWORD)( dinf.total_clusters - dinf.avail_clusters )
			 * (DWORD)dinf.sectors_per_cluster
			 * (DWORD)dinf.bytes_per_sector ;
		printf( " 使用ディスク容量 : " ) ;
		dispSize( size ) ;
		putcrlf() ;
	}

	/*	残りﾃﾞｨｽｸ容量
	------------------ */
	size = (DWORD)dinf.avail_clusters
		 * (DWORD)dinf.sectors_per_cluster
		 * (DWORD)dinf.bytes_per_sector ;
	if ( _optsw.color ) printf( "\x1b[33m" ) ;
	printf( " 残りディスク容量 : " ) ;
	dispSize( size ) ;

	/*	使用率
	----------- */
	pers = (double)dinf.avail_clusters / (double)dinf.total_clusters ;
	pers = ( 1.0L - pers ) * 100.0L ;
	if ( !cdrom ) {								/*  通常ﾄﾞﾗｲﾌﾞ			*/
		printf( "  ディスク使用率(%5.1lf %%)",pers ) ;
		if ( _optsw.color ) printf( "\x1b[m" ) ;
		putcrlf() ;
	} else {									/*  CD-ROM				*/
		printf( "  < CD-ROM >" ) ;
		if ( _optsw.color ) printf( "\x1b[m" ) ;
		putcrlf() ;
	}

	/*	ｸﾗｽﾀｻｲｽﾞ
	------------- */
	size = (DWORD)dinf.sectors_per_cluster * (DWORD)dinf.bytes_per_sector ;
	printf( " クラスタサイズ   : " ) ;
	dispSize( size ) ;
	putcrlf() ;
}

void usage( void )
/*===========================================================================
*	使用方法表示
===========================================================================*/
{
	printf( "カレントディレクトリ情報表示 (C) パオパオ 1993.\n\n" ) ;
	printf( "Usage: cdir [-c] [-i] [-s] [-p]\n" ) ;
	printf( "       -c   色付表示\n" ) ;
	printf( "       -i   ドライブ情報表示\n" ) ;
	printf( "       -s   読み込みセクタ番号表示\n" ) ;
	printf( "       -p   １画面毎表示\n" ) ;
	exit( 1 ) ;
}

void swchk( char *str )
/*===========================================================================
*	ｵﾌﾟｼｮﾝｽｲｯﾁ評価
===========================================================================*/
{
	register int	cnt ;

	for ( cnt=0; cnt<strlen(str); cnt++ ) {
		if ( str[cnt] == '-' || str[cnt] == '/' ) continue ;
		switch ( str[cnt] ) {
		case 'c'	:
		case 'C'	:
			_optsw.color = TRUE ;	break ;
		case 'i'	:
		case 'I'	:
			_optsw.dinf = TRUE ;	break ;
		case 's'	:
		case 'S'	:
			_optsw.sector = TRUE ;	break ;
		case 'p'	:
		case 'P'	:
			_optsw.page = TRUE ;	break ;
		default		:
			usage() ;
		}
	}
}

void clroption( void )
/*===========================================================================
*	ｵﾌﾟｼｮﾝｽｲｯﾁｸﾘｱ
===========================================================================*/
{
	_optsw.color  = 0 ;
	_optsw.dinf   = 0 ;
	_optsw.sector = 0 ;
	_optsw.page   = 0 ;

	_linecnt      = 0 ;
}

void clrdata( void )
/*===========================================================================
*	ﾃﾞｰﾀｸﾘｱ
===========================================================================*/
{
	if ( _direntry != NULL ) free( _direntry ) ;
	if ( _fat != NULL ) free( _fat ) ;
}

int main( int ac,char *av[] )
/*===========================================================================
*	ﾒｲﾝ
===========================================================================*/
{
	int		ret, cnt ;

	clroption() ;								/*  ｵﾌﾟｼｮﾝｽｲｯﾁ/ﾌﾗｸﾞｸﾘｱ	*/
	if ( ac > 1 ) {								/*  引数あり			*/
		for ( cnt=1; cnt<ac; cnt++ ) {
			if ( *av[cnt] == '-' || *av[cnt] == '/' )
				swchk( av[cnt]+1 ) ;			/*  引数ﾁｪｯｸ			*/
			else
				usage() ;						/*  使用方法表示		*/
		}
	}
	ret = init() ;								/*  初期処理			*/
	if ( _optsw.dinf && ret != 4 ) dispDpb() ;	/*  ﾃﾞｨｽｸ情報表示		*/
	switch ( ret ) {
	case 2	:
		printf( "\aFAT用の領域が確保できませんでした." ) ;
		putcrlf() ;
		break ;
	case 3	:
		printf( "\aﾃﾞｨﾚｸﾄﾘｴﾝﾄﾘ用の領域が確保できませんでした." ) ;
		putcrlf() ;
		break ;
	}
	if ( !ret ) {
		if ( dispCdir() == 2 ) {				/*  ｶﾚﾝﾄﾃﾞｨﾚｸﾄﾘ情報表示	*/
			printf( "ファイルが見つかりません." ) ;
			putcrlf() ;
		}
	}
	if ( _optsw.dinf && !_flg.critical )
		dispDrive() ;							/*  ﾄﾞﾗｲﾌﾞ容量表示		*/
	clrdata() ;									/*  ﾃﾞｰﾀｸﾘｱ				*/
	resetdisk() ;								/*  ﾘｾｯﾄﾃﾞｨｽｸ			*/

	return 0 ;
}

