
;   FILENAME: FILES.ASM
;
;   DESCRIPTION: File-handling routines for reading in files, etc.
;
;   MODIFIED: July 15, 1992 - Cut all macros and includes that weren't needed.

%tabsize 4

ifndef  MDL
    display "Error: This module requires that you provide a memory model"
    display "       definition on the command line. I.E. /dMDL=SMALL."
    err ; Force a fatal error
else

    jumps
    ideal			    ; Use TASM's Ideal mode
    model   MDL,pascal		    ; Define the memory model
    P286

include "globals.inc"
include "keytask.inc"

dataseg

NewDTA		DTA	<>

MaxFiles        dw      500
NumFiles	dw	0
FileSeg         dd      0

WildDir 	db	"*.*",0
WildMod 	db	"*.MOD",0
DriveLetter	db	"-:\"
CurPath 	db	65 dup (0)

DriveStr	db	"-:",0
DriveList       db      26 dup (0)

MKLine		db	9 dup (0)
Ext		db	4 dup (0)
ExtBlank	db	"~ ",0
DesBlank        db      "~ ",0

FileDigits	db	"0000",0

CurFile 	dw	0
TopFile 	dw	0

codeseg

proc	DisplayAll
	call	ms_hide
	call	DisplayDriveStuff
	call	DisplayDrives
	call	DisplayFiles,[FileSeg],[TopFile]
	call	DisplayFileMax,[CurFile],[NumFiles]
	call	ms_show
	ret
endp    DisplayAll

proc	DisplayFileMax	CF:word,MF:word
	call	ms_hide
        mov     ax,[CF]
	inc	ax
	call	ConvertKToStr,ax,seg FileDigits,offset FileDigits,4
	mov	bx,14
	call	WriteCol,66,2,seg FileDigits,offset FileDigits
	call	ConvertKToStr,[MF],seg FileDigits,offset FileDigits,4
	mov	bx,14
	call	WriteCol,74,2,seg FileDigits,offset FileDigits
	call	ms_show
        ret
endp    DisplayFileMax

proc    DisplayDriveStuff
	call	ms_hide
        mov     bx,14
	call	WriteCol,2,1,seg DriveLetter,offset DriveLetter
	mov	bx,14
	call	WriteChars,6,68,seg WildMod,offset WildMod,10
	call	ms_show
        ret
endp    DisplayDriveStuff

proc	DisplayDrives
	uses	ds,si,es,di
	local	X:word,Y:word
	call	ms_hide
        mov     ax,@data
	mov	ds,ax
	mov	es,ax
	mov	bx,offset DriveList
	mov	di,offset DriveStr
	mov	cx,0
	mov	[X],50
	mov	[Y],4
@@DriveLoop:
	push	bx
	cmp	[Byte bx],0
	jz	@@EndLoop
	mov	ax,cx
	add	al,'A'
	mov	[es:di],al
	mov	bx,13
	call	WriteCol,[X],[Y],es,di
	cmp	[X],50
	jnz	@@From50
	mov	[X],53
	jmp	@@EndLoop
@@From50:
	mov	[X],50
	inc	[Y]
@@EndLoop:
	pop	bx
	inc	bx
	inc	cx
	cmp	cx,26
	jnz	@@DriveLoop
	call	ms_show
        ret
endp    DisplayDrives

proc    DisplayOneFile  SegS:dword,Line:word,ThisFile:word,CF:word
        uses    ds,si,es,di
	call	ms_hide
        mov     ax,@data
	mov	ds,ax
	mov	ax,[Screen]
	mov	es,ax
	mov	ax,160
	mul	[Line]
	mov	di,ax
	inc	di
	inc	di
	mov	cx,47
@@WriteBackLoop:
	mov	ax,[es:di]
	and	ah,00001111b
	stosw
	loop	@@WriteBackLoop

	lds	si,[SegS]
	mov	ax,size FStruc
	mul	[ThisFile]
	add	si,ax
        cmp     [Byte si+FStruc.TypeOfFile],F_Directory
	jz	@@JustWriteTheDirectory
	mov	ax,seg MKLine
	mov	es,ax
	mov	di,offset MKLine
	mov	cx,8
	push	ds si
@@CopyNameLoop:
	lodsb
	cmp	al,0
	jz	@@FoundPeriod
	cmp	al,'.'
	jz	@@FoundPeriod
	stosb
	loop	@@CopyNameLoop
	inc	si
@@FoundPeriod:
	mov	al,0
	stosb
	mov	cx,3
	mov	di,offset Ext
        cmp     [Byte si],0
	jz	@@ZeroAtExt
@@CopyExtLoop:
	lodsb
	cmp	al,0
	jz	@@ZeroAtExt
	stosb
	loop	@@CopyExtLoop
@@ZeroAtExt:
	mov	al,0
	stosb
	mov	bx,10
	call	WriteChars,2,[Line],seg MKLine,offset MKLine,8
	mov	bx,10
	call	WriteChars,11,[Line],seg Ext,offset Ext,3
	pop	si ds
        mov     bx,[Word si+FStruc.KInFile]
	call	ConvertKToStr,bx,seg kline2,offset kline2+1,3
	call	Write,18,[Line],seg kline2,offset kline2
	mov	bx,10
	add	si,(offset (FStruc).Title)
	call	WriteChars,25,[Line],ds,si,20
	jmp	@@AlmostDone

@@JustWriteTheDirectory:
	mov	bx,4
	call	WriteChars,2,[Line],ds,si,8
	call	Write,11,[Line],seg ExtBlank,offset ExtBlank
	call	Write,18,[Line],seg ExtBlank,offset ExtBlank
	call	Write,25,[Line],seg DesBlank,offset DesBlank
@@AlmostDone:
	mov	ax,[ThisFile]
	cmp	ax,[CF]
	jnz	@@End

	mov	ax,@data
	mov	ds,ax
	mov	ax,[Screen]
	mov	es,ax
	mov	ax,160
	mul	[Line]
	mov	di,ax
	inc	di
	inc	di
	mov	cx,47
@@WriteLoop:
	mov	ax,[es:di]
	or	ah,01010000b
	stosw
	loop	@@WriteLoop
@@End:
	call	ms_show
        ret
endp    DisplayOneFile

proc	DisplayFiles	SegS:dword,Start:word
	uses	ds,si,es,di
	call	ms_hide
        les     di,[SegS]
	mov	bx,4
	mov	cx,[Start]
@@DisplayFileLoop:
	cmp	cx,[NumFiles]
	jge	@@Done
	push	bx cx
	call	DisplayOneFile,es,di,bx,cx,[CurFile]
	pop	cx bx
	inc	cx
	inc	bx
	cmp	bx,22
	jnz	@@DisplayFileLoop
@@Done:
	call	ms_show
        ret
endp	DisplayFiles

proc    CopyFilename    DTAAddr:dword,Dest:dword,TypeFile:word
	uses	ds,es,si,di
	lds	si,[DTAAddr]
	les	di,[Dest]
	mov	ax,[TypeFile]
	mov	[Byte es:di+FStruc.TypeOfFile],al
	add	si,(offset (DTA).Filename)
	mov	cx,13
	rep	movsb
        ret
endp    CopyFilename

proc	CleanFileSegment	SegS:dword,NumToDo:word
	les	di,[SegS]
	xor	dx,dx
	mov	ax,size FStruc
	mov	bx,[NumToDo]
	mul	bx
	mov	cx,ax
	shr	cx,1
	xor	ax,ax
	rep	stosw
	xor	di,di
	ret
endp	CleanFileSegment

proc	GetDrives	DriveArray:dword
	uses	es,di
	les	di,[DriveArray]
	mov	bx,1
@@LoopDrives:
	mov	[Byte es:di],0
	mov	ax,4409h
	int	21h
	jb	@@BottomLoop
	mov	[Byte es:di],1
@@BottomLoop:
	inc	di
	inc	bx
	cmp	bx,26
	jnz	@@LoopDrives
	ret
endp    GetDrives

proc	GetDirs 	StartPos:dword,Wild:dword
	uses	ds,si
	les	di,[StartPos]
	lds	dx,[Wild]
@@DirSearch:
	mov	ah,4Eh
	mov	cx,3Fh
	int	21h
	jb	@@End
@@Internal:
	mov	al,[Byte offset NewDTA+(offset (DTA).FileAttribute)]
	test	al,10h		; Is the file a directory
	jz	@@SkipIt	; Nope
        call    CopyFilename,seg NewDTA,offset NewDTA,es,di,F_Directory
	inc	[Word NumFiles]
	mov	ax,[NumFiles]
	cmp	[MaxFiles],ax
	jz	@@End
	add	di,size FStruc
@@SkipIt:
	mov	ah,4Fh
	int	21h
	jnb	@@Internal
@@End:	ret
endp    GetDirs

proc	GetInfoOnMOD	DTAAddr:dword,Dest:dword
        uses    ds,es,si,di
	local	MODHandle:word
        lds     si,[DTAAddr]
	les	di,[Dest]
	call	CopyFilename,ds,si,es,di,F_File

	push	ds
	mov	ax,3d00h
	push	es
	pop	ds
	mov	dx,di
	int	21h
	pop	ds
	jb	@@BadModule
	mov	[MODHandle],ax

	mov	dx,di
	add	dx,(offset (FStruc).Title)
	push	ds
	mov	ah,3fh
	mov	bx,[ModHandle]
	mov	cx,20
	push	es
	pop	ds
	int	21h
	pop	ds
	jb	@@BadModule

	mov	ax,[Word offset NewDTA+(offset (DTA).Filesize)+1]
	shr	ax,2
	mov	[Word es:di+(offset(FStruc).KInFile)],ax

	mov	ah,3eh
	mov	bx,[MODHandle]
	int	21h
	ret
@@BadModule:
	mov	[Byte es:di+FStruc.BadModule],1
	mov	ah,3eh
	mov	bx,[MODHandle]
        int     21h
        ret
endp    GetInfoOnMOD

proc    GetModules      StartPos:dword,Wild:dword
	uses	ds,si
	mov	ax,[MaxFiles]
	cmp	[NumFiles],ax
	jz	@@End
        les     di,[StartPos]
	lds	dx,[Wild]
@@DirSearch:
	mov	ah,4Eh
	mov	cx,3h
        int     21h
        jb      @@End
@@Internal:
	call	GetInfoOnMOD,seg NewDTA,offset NewDTA,es,di
	inc	[Word NumFiles]
	mov	ax,[NumFiles]
	cmp	[MaxFiles],ax
	jz	@@End
	add	di,size FStruc
	mov	ah,4Fh
	int	21h
	jnb	@@Internal
@@End:	ret
endp	GetModules

proc	ReadFiles
	uses	es,di
	mov	ax,@data
	mov	ds,ax
	mov	[Word NumFiles],0
	mov	[Word CurFile],0
	mov	[Word TopFile],0
	mov	ah,1Ah
	mov	dx,offset NewDTA
	int	21h
	push	ds
	mov	ax,seg CurPath
	mov	ds,ax
	mov	si,offset CurPath
        mov     ah,47h
	mov	dl,0
	int	21h
	pop	ds
	mov	ah,19h
        int     21h
	add	al,'A'
	mov	[DriveLetter],al

	call	CleanFileSegment,[FileSeg],[MaxFiles]
	call	GetDrives,seg DriveList,offset DriveList
	call	GetDirs,es,di,seg WildDir,offset WildDir
	call	GetModules,es,di,seg WildMod,offset WildMod
	mov	ax,[MaxFiles]
	cmp	[NumFiles],ax
	jnz	@@End
;	 call	 TooManyFiles
@@End:	call	SortFiles,[FileSeg],size FStruc,[NumFiles]
	ret
endp	ReadFiles

proc	SortFiles	StartPos:dword,SizeRecord:word,NumToDo:word
	uses	ds,si,es,di,bp
	les	di,[StartPos]
	mov	si,di
	add	di,[SizeRecord]
	mov	cx,[NumToDo]
	or	cx,cx
	jz	@@End
	mov	cx,0
	mov	dx,[SizeRecord]
	mov	bx,0
@@TopLoop:
	push	cx bp
        mov     bp,0
        ; ÄÄÄÄ Compare
	mov	al,[es:bp+si+FStruc.TypeOfFile]
	cmp	al,[es:bp+di+FStruc.TypeOfFile]
	jnz	@@NewRecord

	mov	cx,8
@@ByteByByte:
	mov	al,[es:bp+si]
	mov	ah,[es:bp+di]
	inc	bp
	cmp	al,ah
	jnz	@@DoneCompare
	cmp	al,0
	jnz	@@CheckOther
	clc
	jmp	@@DoneCompare
@@CheckOther:
	cmp	ah,0
	jnz	@@ByteByByte
	stc
@@DoneCompare:
	jb	@@NewRecord

@@SwapThem:
	mov	bx,1
	mov	bp,0
	mov	cx,dx
@@SwapLoop:
	mov	al,[es:bp+si]
	mov	ah,[es:bp+di]
	mov	[es:bp+di],al
	mov	[es:bp+si],ah
	inc	bp
	loop	@@SwapLoop

@@NewRecord:
	pop	bp cx
	inc	cx
	mov	ax,[NumToDo]
	dec	ax
	cmp	cx,ax
	jz	@@FixThem
	add	si,dx
	add	di,dx
	jmp	@@TopLoop
@@FixThem:
	cmp	bx,0
        jz      @@End
	les	di,[StartPos]
	mov	si,di
	add	di,dx
	mov	bx,0
	mov	cx,0
        jmp     @@TopLoop
@@End:  ret
endp    SortFiles

endif   ; ifndef MDL

end

