PUBLIC  FVISIT, FVINIT, FSAVE, .Text, FindFile, Directory

EXTRN	.Msg:Near, .Error0:Near, .InCh:Near, .CLRMsg:Near
EXTRN	$Buffer1:Word, $Buffer2:Word, $BufferNumber:Word
EXTRN	.CAPS:Near, Sound:Near
EXTRN	Separatorline:NEAR, .InvMsg:Near, Switchmenu:Near

;---------------------------------------------------------------------------
	Page ,132
NAME FILE

TITLE File handler

Cursorhome	MACRO
		mov	AH, 2		; set cursor position
		sub	dx, dx
		mov	BH, 0
		int	10h		; request new cursor

	ENDM

cls	macro
	mov	CX, 0			; clear the screen via BIOS
	mov	dx, 184fh
	mov	bh, 7
	mov	AX, 600h
	int 10h
	ENDM

;----------------------------------------------------------------------
Program SEGMENT PARA	PUBLIC  'code'
	ASSUME  CS:Program, DS:Program, ES:Program, SS:Program

;......................................................................

	INCLUDE FDEF.DEF

Maxsize		equ	0F000h
NewfileFlag	equ	10000000b
OF		equ	00000001b

;----------------------------------------------------------------------
; FVisitFile
; FSaveFile
; .ProcessCommandLine
;
; .FLoad		Disk Operation
; .BCBInit		sets up BCB for just loaded file
;----------------------------------------------------------------------

Readonly	equ	0
FileOpen	equ	3Dh
FileRead	equ	3Fh
FileClose	equ	3Eh
FileCreate	equ	3Ch
FileWrite	equ	40h
MSDOS		equ	21h
Cursor		equ	lowintensity*256+178


Defaultfile	db	'WORK.TXT '
VIFT		db	'VISIT FILE <CR>:'
.?Con		db	'SAVE THIS MODIFIED BUFFER (Y/N/CTL-G) ?'
.TextMsg	db	70 dup ('#')
DFMsg		db	'*** Disk Overflow ***'
WriteErr	db	'*** No Filename ***'
NewfileMsg	db	'[NEW FILE]'
NoHandle	db	'*** No Handle Left ***'
Nopath		db	'*** No such Path ***'
AccessDen	db	'*** Access Denied ***'
InternalE	db	'***Internal Error***'
BigMsg		db	'*** File TOO Big ***'
.TQuit		db	'*** User Abort ***'
Rubbish		db	22 dup ('$')
Noth		db	5 dup (0)

;---------------------------------------------------------------------------
FVINIT PROC	NEAR

	call	.ProcessCommandLine
	cmp	CS:$Buffer2, 0
	je	FVOne
		mov	DS, CS:$Buffer2
		call	FLoadFile
FVOne:	mov	DS, CS:$Buffer1
	call	FLoadFile
	ret

FVINIT ENDP

;---------------------------------------------------------------------------
.ProcessCommandLine	PROC	Near


	mov	BL, CS:[80h]
	sub	BH, BH
	mov	Word Ptr CS:[BX+81h], 0
	

	push	DS

 	mov	DS, CS:$Buffer1

	mov	BX, 82h
	call	Transfer_File_Name

	cmp	CS:$Buffer2, 0
	je	.PCLret

		inc	BX			; start transfer from next nam
		mov	DS, CS:$Buffer2
		call	Transfer_File_Name
.PCLret:pop	DS
	ret

.ProcessCommandLine	ENDP

;----------------------------------------------------------------------
; Takes a string from [BX] and puts it into the file-location of the current
; buffer. If there is no filename, then the default filename is loaded.

Transfer_File_Name	PROC	NEAR
	xor	DI, DI				; DI will act as a counter

TFN1:	mov	AL, CS:[BX+DI]			; transfer until a space is
	cmp	AL, ' '				; found
	je	TFN2
	cmp	AL, 0
	je	TFN2
	mov	DS:BCB.File[DI], AL
	inc	DI
	jmp	TFN1
TFN2:	mov	DS:BCB.File[DI], 0		; -> ASCIIZ
	cmp	DI, 0				; if the first character was
	je	No_FileName_On_Line		; a ' ', put something special
	add	BX, DI				; remem where next one starts
	cmp	BX, 100h
	jbe	TFN3
	mov	BX, 80h
TFN3:	ret

No_FileName_On_Line:
	mov	BX, Offset Defaultfile
	call	Transfer_File_name
	ret
Transfer_File_Name	ENDP

;---------------------------------------------------------------------------
; File Not Found Handler
DOSERROR:
	cmp	AX, 2
	je	DOSERROR2
	cmp	AX, 3
	je	DOSERROR3
	cmp	AX, 4
	je	DOSERROR4
	cmp	AX, 5
	je	DOSERROR5
	mov	SI, Offset InternalE
	mov	CX, 20
	jmp	.Error0


; new file
DOSERROR2:
	mov	Byte Ptr DS:[100h], EOF
	mov	DS:BCB.FCursor, 100h
	mov	DS:BCB.FEnd, 100h
	mov	DS:BCB.AuxScrStart, 100h
	mov	DS:BCB.AuxCursor, 100h
	mov	DS:BCB.ScrStart, 100h
	mov	DS:BCB.FCurCol, 1
	mov	DS:BCB.Mark, 100h
	mov	DS:BCB.ScrCursor, 0
	mov	DS:BCB.Dirty, FALSE
	mov	DS:BCB.EDMode, 0
	mov	DS:BCB.UnUsed, FALSE
	mov	SI, Offset NewfileMsg
	mov	CX, 10
	jmp	.Msg

; Invalid Pathname
DOSERROR3:
	mov	SI, Offset NoPath
	mov	CX, 20
	jmp	.Error0


; No Handle Available
DOSERROR4:
	mov	SI, Offset NoHandle
	mov	CX, 22
	jmp	.Error0


; Access denied
DOSERROR5:
	mov	SI, Offset AccessDen
	mov	CX, 21
	jmp	.Error0

;...........................................................................
FLoadFile	PROC	Near

	mov	AL, Readonly
	mov	AH, FileOpen
	mov	DX, Offset BCB.File
	int	MSDOS
	jnc	FL1
		jmp	DOSERROR
FL1:	mov	BX, AX			; holds file handle
	mov	DX, 100h		; holds the filepointer
	mov	CX, 0F001h		; min bufferlength for real work
	mov	AH, FileRead
	int	MSDOS

	cmp	AX, 0F000h
	jae	OFERROR

	push	AX
	mov	AH, FileClose
	int	MSDOS
	pop	AX
	jnc	FL2
	jmp	DOSERROR

FL2:	add	AX, 100h		; and adjust for our buffer starts at
	mov	DS:BCB.FEnd, AX		; 100h
	mov	BX, AX
	mov	Byte Ptr DS:[BX], 1Ah	; set the eof character

	mov	DS:BCB.EDmode, 0	; Fundamental
	mov	DS:BCB.Dirty, FALSE	; saved buffer
	mov	DS:BCB.Scrend, 0	; screen end
	mov	DS:BCB.Scrcursor, 0	; screen cursor
	mov	DS:BCB.Unused, FALSE

	mov	DS:BCB.FCurCol, 1

	mov	AX, 0100h

	mov	DS:BCB.ScrStart,  AX	
	mov	DS:BCB.FCursor,	AX
	mov	DS:BCB.AuxScrStart,  AX	
	mov	DS:BCB.AuxCursor, AX
	mov	DS:BCB.Mark, AX
	mov	DS:BCB.FOldCursor, AX
	mov	DS:BCB.FOldCurCol, AX

	ret

;---------------------------------------------------------------------------
; File TOO Big
OFERROR:
	mov	AH, FileClose
	int	MSDOS

	mov	CX, 20
	mov	SI, Offset BigMsg
	call	.Msg
	mov	DS:BCB.File, '-'
	ret


FLoadFile	ENDP


;----------------------------------------------------------------------
FVISIT PROC	NEAR

	call	.CLRMsg			; first put up the visit file msg
	mov	SI, Offset ViFT
	mov	CX, 16
	call	.Msg
	mov	SI, CX			; now calculate the screen message
	add	SI, SI
	add	SI, StartofMsgField	
	mov	DI, Offset BCB.File	; load to the filename DS:DI
	mov	DL, CR			; and end everything with a CR
	call	.Text			; result in BCB.File, CX: # of chars

	cmp	CX, 0
	je	WrErr

	push	SI
	push	BX
	call	.?Save			; ask for confirmation
	pop	BX
	pop	SI

	mov	DI, Offset BCB.File	; Filename Start

	call	FLoadFile		; and load the file to 100h
	ret

WrErr: mov	SI, Offset WriteErr
	mov	CX, 19
	jmp	.Error0

FVISIT ENDP


;**********************************************************************
FSAVE  PROC	Near

	mov	DX, Offset BCB.File	; here I should first rename
	xor	CX, CX			; no attribute
	mov	AH, Filecreate
	int	MSDOS
	jnc	FS1
	jmp	DOSERROR
FS1:	mov	BX, AX			; file handle
	mov	CX, DS:BCB.FEnd
	sub	CX, 100h		; # bytes to be written
	mov	DX, 100h
	push	CX
	mov	AH, FileWrite
	int	MSDOS
	pop	CX
	jnc	FS2
	jmp	DOSERROR	
FS2:	push	AX
	mov	AH, FileClose
	int	MSDOS
	pop	AX	
	cmp	AX, CX
	jne	DiskFull
	mov	DS:BCB.Dirty, FALSE
	ret

FSAVE  ENDP


DiskFull	PROC	NEAR
	mov	SI, Offset DFMsg
	mov	CX, 21
	jmp	.Error0
DiskFull	ENDP


;***************************************************************************
;----------------------------------------------------------------------
; accepts text and puts it into [DI]. The exit character is in AL.
; [SI] points to the current character on the screen
; other functions:
;
;	CTL-G	cancel and exit
;	CTL-U	cancel and retry
;	CTL-H	backspace one character
;	ESC	parse for the filename
;
; returns on exit in CX the number of received characters, in DI the start of
; the message ( as it was received on entry ).
;

Exitcharacter	db	CR

.Text	PROC	Near

	xor	BX, BX			; 0 characters received
	mov	CS:Exitcharacter, DL

.TextLoop:
	mov	AX, Cursor		; set the cursor
	mov	ES:[SI+BX], AX


.Text0:	call	.InCh
	jz	.Text0

	cmp	AL, CS:Exitcharacter	; if we have an end character
	je	.TextEnd
	cmp	AL, ESC			; if we wish to parse for a file
	je	.TextParse
	cmp	AL, 21			; if we wish to retry = C-U
	je	.TextRedo
	cmp	AL, 7			; if we wish to quit = C-G
	je	.TextQuit
	cmp	AL, 8			; if we wish to backspace
	je	.TextDel

.TextChar:				; if we just wish to add a char
	mov	CS:[BX+Offset .TextMsg], AL

	mov	AH, lowintensity	; put it to screen
	mov	ES:[BX+SI], AX

	inc	BX			; next character.
	inc	SI			; advance the screen by one extra.

	jmp	.TextLoop

;...........................................................................
.TextRedo:	
	cmp	BX, 0				; are there 0 chars ?
	je	.TextLoop
	mov	AX, ' '+lowintensity*256	; no, then clear from scr
	mov	ES:[BX+SI], AX
	dec	BX				; one less char to clear
	dec	SI				; but adjust for scr *2
	jmp	.TextRedo

;...........................................................................
.TextQuit:
	call	.CLRMsg
	xor	BX, BX
	mov	SI, Offset .TQuit
	mov	CX, 18
	jmp	.Error0

;...........................................................................
.TextEnd:
	mov	CX, BX				; we have received BX chars
	cmp	cx, 0
	je	.TEnd2
	mov	SI, Offset .TextMsg		; This is where we stored our
						; temporary string: DI holds
						; where it should be
.TEnd1:	mov	AL, CS:[SI]			; this transfers everything
	mov	DS:[DI], AL			; to the desired location
	inc	DI
	inc	SI
	loop	.TEnd1

.TEnd2:	mov	Byte Ptr DS:[DI], 0		; oh, and signal ASCIIZ flag
	push	bx
	call	.CLRMsg				; clear the messagefield
	pop	cx
	ret
;...........................................................................

.Textdel:
	cmp	BX, 0				; if there are 0 chars...
	je	.TextDelErr
	mov	AX, ' '+lowintensity*256	; clear the cursor
	mov	ES:[BX+SI], AX
	dec	SI				; adjust to point to
	dec	BX				; previous character
	jmp	.TextLoop

.TextDelErr:
	call	Sound
	jmp	.Text0				; do nothing

CannotParse:
	call	Sound
	jmp	.text0
;...........................................................................
.TextParse:
	mov	AL, CS:Rubbish+1
	cmp	AL, ':'
	je	CannotParse
	push	DS
	mov	AX, CS
	mov	DS, AX
	mov	DX, Offset Rubbish		; DS:DX -> Rubbish
	mov	AH, 1Ah
	int	MSDOS				; DTA set

	call	AddStars

	mov	DX, Offset .TextMsg		; request first directory name
	xor	CX, CX				; no attributes
	mov	AH, 4Eh
	int	MSDOS
	jc	NoSuchFile

	mov	AH, 4Fh				; request another such file
	int	MSDOS
	jnc	Multiplefiles

	pop	DS				; now we don't need these
						; pointers anymore.

; When we reach here, we have a unique filename in rubbish.
FNT:	mov	AL, CS:[BX+(Offset Rubbish)+1Eh] ; get one new character
	cmp	AL, NUL				; check if it is the end
	je	FNTEnd
	mov	CS:[Offset .TextMsg+BX], AL	; and add it to our name

	mov	AH, nocolor			; and put it to the screen
	mov	ES:[SI+BX], AX

	inc	BX				; next character
	inc	SI
	jmp	FNT

FNTEnd:	mov	AX, Cursor			; reset the cursor
	mov	ES:[SI+BX], AX
	jmp	.Text0				; and wait for more commands


MultipleFiles:
	pop	DS
	call	Sound
	jmp	.Text0

NoFileMsg	db	'*** No such File ***'
NoSuchFile:
	pop	DS
	call	.CLRMsg
	mov	SI, Offset NoFileMsg
	mov	CX, 20
	jmp	.Error0

;...........................................................................
AddStars	PROC	NEAR		; pads with either * or *.*

	push	AX
	mov	AX, BX
AddAgain:
	dec	BX
	jz	Endreached
	cmp	Byte Ptr CS:[Offset .TextMsg+BX], '.'
	jne	Addagain

FoundPeriod:
	mov	BX, AX
	mov	Byte Ptr CS:[BX+Offset .TextMsg], '*'	; convert to ASCIIZ
	mov	Byte Ptr CS:[BX+Offset .TextMsg+1], 0
	pop	AX
	ret
EndReached:
	mov	BX, AX
	mov	Byte Ptr CS:[BX+Offset .TextMsg], '*'	; convert string to ASCIIZ
	mov	Byte Ptr CS:[BX+Offset .TextMsg+1], '.'	; parse format
	mov	Byte Ptr CS:[BX+Offset .TextMsg+2], '*'
	mov	Byte Ptr CS:[BX+Offset .TextMsg+3], 0
	pop	AX
	ret

AddStars	ENDP

.Text  ENDP

;----------------------------------------------------------------------
.NFile PROC	NEAR	; archaic but public
	ret

.NFile ENDP

;..............................
.?Save PROC	Near

	cmp	DS:BCB.Dirty, TRUE
	jne	NoQuestion

	mov	SI, Offset .?Con
	mov	CX, 38
	call	.Msg

.?Save0:call	Sound

.?Save1:call	.InCH
	jz	.?Save1
	call	.CAPS
	cmp	AL, 'N'
	je	.?Save2
	cmp	AL, CTL_G
	je	AbortQuick
	cmp	AL, 'Y'
	jne	.?Save0

	jmp	FSave

.?Save2:
NoQuestion:
	ret
AbortQuick:
	mov	SI, Offset .TQuit
	mov	CX, 18
	jmp	.Error0

.?Save ENDP

;---------------------------------------------------------------------------
Scraparea	equ	Offset BCB.File+100
Dirmaskmsg	db	'Directory Mask [*.*]: '
Entries		db	44 dup ( '|')

Directory	PROC	Near
	call	.CLRMsg			; first put up the visit file msg
	mov	SI, Offset Dirmaskmsg
	mov	CX, 22
	call	.Msg
	mov	SI, CX			; now calculate the screen message
	add	SI, SI
	add	SI, StartofMsgField	
	mov	DI, Scraparea		; load to some free space
	mov	DL, CR			; and end everything with a CR
	call	.Text			; in BCB.File+100, CX: # of chars

	cmp	cx, 2			; more than 2 characters
	ja	Dir2

	cmp	cx, 1			; one character filename
	je	Dir2

	mov	bx, scraparea
	cmp	cx, 0			; no file so default to *.*
	je	Dir1

	cmp	byte ptr Ds:[bx+1], ':'	; default drive
	jne	Dir2
	add	bx, 2	
	
Dir1:	mov	Byte Ptr DS:[bx],   '*'	; default mask : *.*
	mov	Byte Ptr DS:[bx+1], '.'
	mov	Byte Ptr DS:[bx+2], '*'
	mov	Byte Ptr DS:[bx+3],  0
	add	cx, 3
	
Dir2:	push	ds			; set DTA to entries
	push	cs
	pop	ds
	mov	dx, offset entries
	mov	ah, 1Ah
	int	MSDOS
	pop	ds

	mov	dx, Scraparea		; get first file
	sub	cx, cx
	mov	ah, 4Eh
	int	MSDOS
	jc	faildir

	cls
	cursorhome

Another:call	printentry
	mov	ah, 4Fh			; get another file
	int	MSDOS
	jc	Allreported
	jmp	Another

printentry	proc	near
	mov	cx, 20
	mov	si, offset entries +30

printentry1:
	mov	dl, cs:[si]
	inc	si
	cmp	dl, 0
	je	printedentry
	mov	ah, 6			; print one character
	int	MSDOS
	loop	printentry1

printedentry:
	mov	dl, ' '
	mov	ah, 6
printspaces:
	int	MSDOS
	loop	printspaces

	ret
printentry	endp


Allreported:
	mov	si, offset presskey
	mov	cx, 30
	call	.InvMsg
Allreported1:
	call	.Inch
	jz	Allreported1

	call	.CLRMsg			; restore msgarea
	call	Separatorline		; restore separator line for windows
	mov	ax, 7*256+0		; reinitialize last line
	jmp	Switchmenu

faildir:mov	si, offset dirfailmsg
	mov	cx, 31
	jmp	.Error0

presskey	db	'Press any key to return to MAX'
dirfailmsg	db	'*** No Such Accessible File ***'

Directory	ENDP
;---------------------------------------------------------------------------
FindFile	PROC	NEAR
	
	mov	SI, Offset InImplementation
	mov	CX, 21
	jmp	.Msg

InImplementation	db	'* In Implementation *'
;	mov	BX, 0
;	mov	CX, CS:$Buffernumber

;TBLoop:	mov	DS, CS:[BX+Offset $Buffer1]
;	shr	BX, 1
;	mov	AX, BX
;	add	BX, BX
;	add	BX, 2
;	push	AX
;	cmp	AX, CS:ActiveBuffer
;	je	SWI

FindFile	ENDP
	PROGRAM ENDS
END
