unit unitDirList{@||DirList};

(*
/*

CLASS {UnitDirList||DirList|_similar_to_KOL_PDirList},
UNTESTED, RECURSIVE, BITWISE:

IMPORT: {File_path}, {Sorting}, {String_functions} .

BASE CLASS: {Sorting} .

	STR Path|_directory, READ
	STR Names|_files[], READ
	{File_path}.{file_detail} Files|_info[], READ

FUN NewDirList(
STR Path|_directory, STR Mask|_files, INT Attr|ibutes_mask) ==> {DirList}, NEW
	:
	RESULT = {DirList}
	RESULT.ScanDirectory(Path, Mask, Attr) .
	
METHOD ScanDirectory(
STR Directory|_path, STR Mask|_files, INT Attr|ibutes_mask)
	:
	Path = Directory
	Names[].Clear
	Files[].Clear
	Catalog(Path, Names[])
	CASE Mask != "*.*" ?
		 FOR s IN Names[* DOWNTO 0] :
		     CASE !mask_match(s, Mask) ?
		          Names[].Delete(s.Index)
		          CONTINUE s ;
		 ;
	;
	------------------- 'scan file information'
	FOR s IN Names[] :
	    {file_detail} fi|nformation = File_detail(Path.Trailing_slash s)
	    Files[] << fi.Dismiss ;
	CASE Attr == 0 ? ==> ;
	FOR s IN Names[* DOWNTO 0] :
		FOR a IN {File_path}.{file_attr} :
		    CASE attr_mask(a) & Attr == 0 ?
	             Names[].Delete(s.Index)
	             Files[].Delete(s.Index) ;
		;
	; .
	
FUN attr_mask({file_attr} A|ttribute) ==> INT :
	CASE A ?
	['READONLY']:	RESULT = FILE_ATTRIBUTE_READONLY
	['HIDDEN']:		RESULT = FILE_ATTRIBUTE_HIDDEN
	['SYSTEM']:		RESULT = FILE_ATTRIBUTE_SYSTEM
	['DIRECTORY']:	RESULT = FILE_ATTRIBUTE_DIRECTORY
	['ARCHIVE']:	RESULT = FILE_ATTRIBUTE_ARCHIVE
	['NORMAL']:		RESULT = FILE_ATTRIBUTE_NORMAL
	['TEMPORARY']:	RESULT = FILE_ATTRIBUTE_TEMPORARY
	['COMPRESSED']:	RESULT = FILE_ATTRIBUTE_COMPRESSED
	['OFFLINE']:	RESULT = FILE_ATTRIBUTE_OFFLINE ; .
	
FUN mask_match(
STR S|tring_to_check, STR Mask|_to_compare_with) ==> BOOL, RECURSIVE
	:
	CASE Mask[0] ?
	["*"]: 
		CASE Mask.Len == 1 ? RESULT = TRUE ==> ;
		FOR i IN [0 TO S.Len-1] :
		    CASE mask_match(S[i TO *], Mask[1 TO *]) ?
		         RESULT = TRUE ==> ;
		;
			
	["?"]: 
		CASE Mask.Len == 1 && S.Len == 1 ? RESULT = TRUE ==> ;
		RESULT = mask_match(S[1 TO *], Mask[1 TO *])
	ELSE
		FOR i IN [0 TO S.Len-1] :
		    CASE Mask[i] IN "*?" ?
		         RESULT = mask_match(S[i TO *], Mask[i TO *]) ==> ;
		    CASE S[i] != Mask[i] ? ==> ;
		;
		RESULT = S.Len == Mask.Len ; .
		
------------- 'information'

METHOD Count|_of_items ==> INT := Names[].Count .
		
FUN IsDirectory(
{DirList} DL|ist_of_files, INT Index|_in_list) ==> BOOL :
	RESULT = DL.Files[Index].Attrib['DIRECTORY'] .
	
CONST INT {int_file_attributes} :
  FILE_ATTRIBUTE_READONLY             = 0x00000001
  FILE_ATTRIBUTE_HIDDEN               = 0x00000002
  FILE_ATTRIBUTE_SYSTEM               = 0x00000004
  FILE_ATTRIBUTE_DIRECTORY            = 0x00000010
  FILE_ATTRIBUTE_ARCHIVE              = 0x00000020
  FILE_ATTRIBUTE_NORMAL               = 0x00000080
  FILE_ATTRIBUTE_TEMPORARY            = 0x00000100
  FILE_ATTRIBUTE_COMPRESSED           = 0x00000800
  FILE_ATTRIBUTE_OFFLINE              = 0x00001000 .
	
FUN dwFileAttributes({file_detail} FD|etails) ==> INT,
PUBLIC
	:
	FOR fa IN {file_attr} :
	    CASE FD.Attrib[fa] ?
	         CASE fa ?
	         ['READONLY']:	RESULT |= FILE_ATTRIBUTE_READONLY
             ['HIDDEN']:	RESULT |= FILE_ATTRIBUTE_HIDDEN
             ['SYSTEM']:	RESULT |= FILE_ATTRIBUTE_SYSTEM
             ['DIRECTORY']:	RESULT |= FILE_ATTRIBUTE_DIRECTORY
             ['ARCHIVE']:	RESULT |= FILE_ATTRIBUTE_ARCHIVE
             ['NORMAL']:	RESULT |= FILE_ATTRIBUTE_NORMAL
             ['TEMPORARY']:	RESULT |= FILE_ATTRIBUTE_TEMPORARY
             ['COMPRESSED']:RESULT |= FILE_ATTRIBUTE_COMPRESSED
             ['OFFLINE']:	RESULT |= FILE_ATTRIBUTE_NORMAL ;
	    ;
	; .
		
--------- 'delete items'

METHOD Delete|_file(INT Index|_of_file) :
	Names[].Delete(Index)
	Files[].Delete(Index) .
		
------------------------ 'sorting'
		
ENUM {sort_option||sortdirrules} :
	'sdrFoldersFirst	|| FOLDERS_FIRST',
	'sdrCaseSensitive	|| CASE_SENSITIVE',
	'sdrByName			|| BY_NAME|_FILE',
	'sdrByExt			|| BY_EXT|ENSION',
	'sdrBySize			|| BY_SIZE|_OF_FILE',
	'sdrBySizeDescending|| BY_SIZE_DESC|ENDING',
	'sdrByDateCreate	|| BY_DATE_CREATE|D',
	'sdrByDateChanged	|| BY_DATE_CHANGE|D',
	'sdrByDateAccessed	|| BY_DATE_ACCESS|ED',
	'sdrInvertOrder		|| INVERT_ORDER' .
	
{sort_option} sort_op|tions[]

METHOD Sort|_using_options(
{sort_option} Options|_to_sort[]) 
	:
	sort_op[].Clear
	FOR op IN Options[] : sort_op[] << op ;
	Data_sort(Count) .
	
OVERRIDE data_compare(
INT E1|_index, INT E2|_index) ==> INT
	:
	BOOL case|_sensitivity = FALSE
	FOR op IN sort_op[] :
	    CASE op ?
	    ['FOLDERS_FIRST']:
	    	CASE ?
	    	[IsDirectory(THIS, E1) && !IsDirectory(THIS, E2)] ? RESULT = -1
	    	[!IsDirectory(THIS, E1) && IsDirectory(THIS, E2)] ? RESULT = +1
	    	;
	    ['CASE_SENSITIVE']: case = TRUE
	    ['BY_NAME']:
	    	CASE ?
	    	[Names[E1] < Names[E2]] ? RESULT = -1
	    	[Names[E1] > Names[E2]] ? RESULT = +1 ;
	    ['BY_EXT']:
	    	CASE ?
	    	[Names[E1].Ext < Names[E2].Ext] ? RESULT = -1
	    	[Names[E1].Ext > Names[E2].Ext] ? RESULT = +1 ;
	    ['BY_SIZE']:
	    	CASE ?
	    	[Files[E1].Size < Files[E2].Size] ? RESULT = -1
	    	[Files[E1].Size > Files[E2].Size] ? RESULT = +1 ;
	    ['BY_SIZE_DESC']:
	    	CASE ?
	    	[Files[E1].Size < Files[E2].Size] ? RESULT = +1
	    	[Files[E1].Size > Files[E2].Size] ? RESULT = -1 ;
	    ['BY_DATE_CREATE']:
	    	CASE ?
	    	[Files[E1].Creation < Files[E2].Creation] ? RESULT = -1
	    	[Files[E1].Creation > Files[E2].Creation] ? RESULT = +1 ;
	    ['BY_DATE_CHANGE']:
	    	CASE ?
	    	[Files[E1].Modified < Files[E2].Modified] ? RESULT = -1
	    	[Files[E1].Modified > Files[E2].Modified] ? RESULT = +1 ;
	    ['BY_DATE_ACCESS']:
	    	CASE ?
	    	[Files[E1].Accessed < Files[E2].Accessed] ? RESULT = -1
	    	[Files[E1].Accessed > Files[E2].Accessed] ? RESULT = +1 ;
	    ['INVERT_ORDER']: RESULT = -RESULT ;
	    CASE RESULT != 0 ? ==> ;
	;
	RESULT = E1 - E2 .
	
OVERRIDE data_swap(
INT E1|_index, INT E2|_index)
	:
	STR temp_s|tring = Names[E1]
	Names[E1] = Names[E2]
	Names[E2] = temp_s
	{file_detail} temp_f|ile_detail = Files[E1].Dismiss
	Files[E1] = Files[E2].Dismiss
	Files[E2] = temp_f.Dismiss .
	
		
END
*/
*)

interface

uses KOL;

function IsDirectory(DL: PDirList; i: Integer): Boolean;

implementation

function IsDirectory(DL: PDirList; i: Integer): Boolean;
begin
	Result := DL.IsDirectory[i];
end;

end.
 
