(*
/*

CLASS {NATIVE_Scan_cat|alog_directory|DELPHI_FPC}, 
UNTESTED, NATIVE, BITWISE:

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

NATIVE: @
		"uses System_functions, NATIVE_Scan_cat"
		"{$IFDEF FPC}"
		"	, LazFileUtils"     
		"{$ENDIF}"     
		"{$IFDEF LINUX} "
		"	{$IFDEF fileutil_bug_fixed_in_FPC_LAZARUS}"
		"		, fileutil "
		"	{$ENDIF not_fixed}"
		"	, BaseUnix, Unix"
		"{$ELSE} "
		"		, Windows, ShellApi"
		"{$ENDIF};" .
		
NATIVE: "///COPY NATIVE_scan_cat.pas" .

*/
*)


unit NATIVE_Scan_cat;

interface
	uses Windows, 
		{$IFDEF KOL} KOL 
		{$ELSE} 
			Classes
			{$IFDEF FPC}
				, SysUtils, LazFileUtils
			{$ENDIF} 
		{$ENDIF} ;
	

{$IFDEF FPC}
type TSearchInfo = class
	 public
		sr: TSearchRec;
	 end;
{$ENDIF}
var Handles: {$IFDEF KOL} PList {$ELSE} TList {$ENDIF};
function Allocate_handle_scan_cat: Integer;
	
implementation

function Allocate_handle_scan_cat : Integer;
begin
	if Handles = nil then
	   Handles := {$IFDEF KOL} NewList {$ELSE} TList.Create() {$ENDIF} ;
	RESULT := Handles.IndexOf(nil);
	if RESULT < 0 then
	begin
	   RESULT := Handles.Count;
	   Handles.Add(nil);
	end; 
end;

end.
(*
/*

FUNCTION Create_scan_cat(
STR Path|_to_scan, 
STR Items|_names[],
{file_detail} Details|_corresponding[]) ==> INT
	:
	RESULT = do_create_scan_cat(Path, Items[])
	CASE Items[].Count==1 ? 
	     Details[] << File_detail(Path.Trailing_slash Items[0])
	     CASE Details[*].Attrib & DIRECTORY != 0 ? Items[*] = _.Trailing_slash ;
         //DEBUG: "first file is " Items[0]
         //       ", attr=" Details[0].Attrib.Hex2
         //       ", RESULT=" RESULT #NL ;
	; .
	
FUN do_create_scan_cat(
STR Path|_to_scan,
STR Items|_names[]) ==> INT, NATIVE :
	STR ex_path|_wildcarded = Path.Trailing_slash "*"
	NATIVE @
	"var scan: Integer;" 
	"{$IFDEF FPC}"
	"	var si: TSearchInfo;"
	"	var buf: array[0..260] of Char; len: Integer; "
	"{$ELSE}"     
	"	var F:TWin32FindData;"
	"{$ENDIF}"     
	"var s: String;"     
	"RESULT := -1;"    
	"	s := X_ex_path;"     
    "	{$IFDEF FPC}"
    "	    si := TSearchInfo.Create;"
    "	    len := 259; "
    "	    if len > Length(s) then len := Length(s);"
    "	    move(s[1], buf[0], len+1);"
    "	    scan := FindFirstUTF8(s, 0, si.sr);"
    "	{$ELSE}"     
    "		scan := FindFirstFile( PChar( s ), PWin32FindData( @ F )^);"
    "	{$ENDIF}"     
    "if scan <> -1 then"     
    "begin"     
    "	RESULT := Allocate_handle_scan_cat();"
    "	Handles{$IFDEF KOL}.Items{$ENDIF}[RESULT] := {$IFDEF FPC} "
    "													si "
    "												 {$ELSE} "
    "													Pointer(scan)"
    "												 {$ENDIF};" 
    "	{$IFDEF FPC}"
    "		X_Items.Add(-1, si.sr.Name);"     
    "	{$ELSE}"
    "		X_Items.Add(-1, F.cFileName);"
    "	{$ENDIF}"     
    "end;"
    .
    
FUNCTION Scan_cat(
INT Handle|_of_scan_cat,
STR Items|_names[],
{File_path}.{file_detail} Details|_corresponding[]) 
==> BOOL RESULT|_scanning_finished
	:
	INT attr|ibutes[]
	REAL size_dates[]
	STR filename = do_scan_cat(Handle, attr[], size_dates[]) 
	RESULT = filename == ""
	CASE RESULT ? ==> ;
	Items[] << filename if(attr[0] & DIRECTORY <> 0, Path_sep)
	Details[] << {file_detail}(
		Attrib = attr[0],
		Size= size_dates[0],
		Creation= size_dates[1], 
		Modified= size_dates[2], 
		Accessed= size_dates[3])  
	.
	
FUN do_scan_cat(
INT Handle|_scanner, INT attr|ibutes[], REAL size_dates[]) ==> STR, NATIVE
    :
	CASE Handle < 0 ? ==> ;
NATIVE @
	"var LT: TFileTime;"
	"var ST: TSystemTime;" 
	"var DT: TDateTime;"
	"{$IFDEF FPC}"
	"	var si: TSearchInfo;"  
	"	var a: Integer;"     
	"{$ELSE}"     
	"	var F: TWin32FindData;"
	"{$ENDIF}"     
	"var scan: Integer;"   
	"var found: Boolean;"    
	"var s: String;"
    "var q, sz: Double;"
    "	 q := 24.0 * 3600000;"
	"{$IFDEF FPC} "
	"	si := TSearchInfo(Handles {$IFDEF KOL} .Items {$ENDIF} [X_Handle]);"
	"	RESULT := '';"     
	"	if si = nil then Exit;"     
	"	RESULT := si.sr.Name;"
	"	a := 0;"     
	"	if (si.sr.Attr and faDirectory) <> 0 then a := a + 16;"
	"	if (si.sr.Attr and faReadOnly) <> 0 then a := a + 1;"     
	"	if (si.sr.Attr and faHidden) <> 0 then a := a + 2;"   
	"	{$IFDEF LINUX}"
	"	if RESULT[1] == '.' then a := a or 2;"     
	"	{$ENDIF}"     
	"	if (si.sr.Attr and faSysFile) <> 0 then a := a + 4;"   
	"	X_attr.Add(-1, a);"
	"	sz := si.sr.Size;"
    "		X_size_dates.Add(-1, sz);"    
    "       X_size_dates.Add(-1, FileDateToDateTime(si.sr.Time) * q);"
    "       X_size_dates.Add(-1, FileDateToDateTime(si.sr.Time) * q);"
    "       X_size_dates.Add(-1, FileDateToDateTime(si.sr.Time) * q);"
	"	found := 0=FindNextUTF8(si.sr);"
	"	if found then Exit;"     
	"{$ELSE} "
	"	FillChar(F, 0, Sizeof(F));"
	"	scan := Integer(Handles {$IFDEF KOL} .Items {$ENDIF} [X_Handle]);"
	"	found := FindNextFile(scan, PWin32FindData( @ F )^);"  
	"if found then"
	"begin"
	"	RESULT := F.cFileName;"
	"	X_attr.Add(-1, F.dwFileAttributes);"
    "	sz := F.nFileSizeLow + F.nFileSizeHigh * 4294967296.0;"
    "		X_size_dates.Add(-1, sz);"
    ""     
    "   FileTimeToLocalFileTime(F.ftCreationTime, LT);"
    "   	FileTimeToSystemTime(LT, ST);"
    "	{$IFDEF KOL} SystemTime2DateTime(ST, DT);"
    "	{$ELSE} DT := SystemTimeToDateTime(ST);"
    "	{$ENDIF}"
    "    	X_size_dates.Add(-1, DT * q);"
    ""     
    "   FileTimeToLocalFileTime(F.ftLastWriteTime, LT);"
    "   	FileTimeToSystemTime(LT, ST);"
    "	{$IFDEF KOL} SystemTime2DateTime(ST, DT);"
    "	{$ELSE} DT := SystemTimeToDateTime(ST);"
    "	{$ENDIF}"     
    "    	X_size_dates.Add(-1, DT * q);"
    ""     
    "   FileTimeToLocalFileTime(F.ftLastAccessTime, LT);"
    "   	FileTimeToSystemTime(LT, ST);"
    "	{$IFDEF KOL} SystemTime2DateTime(ST, DT);"
    "	{$ELSE} DT := SystemTimeToDateTime(ST);"
    "	{$ENDIF}"     
    "    	X_size_dates.Add(-1, DT * q);"
    "	Exit;"     
	"end;"
	"{$ENDIF}"     
	"{$IFDEF FPC}"
	"	FindCloseUTF8(si.sr);"     
	"{$ELSE}"
	"	CloseHandle(scan);"     
	"{$ENDIF}"     
	"Handles {$IFDEF KOL} .Items {$ENDIF} [X_Handle] := nil;"     
	.
	
FUN Release_scan_handle(INT Handle|_of_scan_cat), NATIVE : @
	"var {$IFDEF FPC} si: TSearchInfo; {$ELSE} scan: Integer; {$ENDIF}"        
	"{$IFDEF FPC} "
	"	si := TSearchInfo(Handles {$IFDEF KOL} .Items {$ENDIF} [X_Handle]);" 
	"	FindCloseUTF8(si.sr);"     
	"{$ELSE}"     
	"	scan := Integer(Handles {$IFDEF KOL} .Items {$ENDIF} [X_Handle]);"
	"	FindClose(scan);"     
	"{$ENDIF}" .


END

*/
*)
