PUBLIC  FHelp

EXTRN	LastLabel:Near
EXTRN	.Screen:Near, .Error0:Near, .InCH:Near, Sound:near, .Msg:Near
EXTRN	Separatorline:Near
EXTRN	.CLRMsg:Near
EXTRN	Switchmenu:Near

;---------------------------------------------------------------------------
	; This module executes the HELP interpreter. It reads in the file
	; MAX.HLP, and executes the user-typed commands. It only uses
	; standard DOS and BIOS calls for Keyboard, Diskette and Screen Access

Title Help Facility

program segment	 para	public	'code'
	assume  cs:program, ds:program, es:program, ss:program

;---------------------------------------------------------------------------
	INCLUDE		FDEF.DEF

	readonly	equ	0	; MSDOS call numbers
	fileopen	equ	3dh
	fileread	equ	3fh
	fileclose	equ	3eh
	msdos		equ	21h

	backspace	equ	8	; options other than  numbers
	exit1		equ	1Bh	; quit via ESC, SPACE or CTL-G
	exit2		equ	' '
	exit3		equ	7

	cursor	macro	x, y		; SCREEN macro: moves the cursor
		mov	dh, x		; to location x, y
		mov	dl, y
		mov	ah, 2
		mov	bh, 0
		int	10h
	endm

	cls	macro			; SCREEN
		mov	cx, 0		; clears the screen
		mov	dx, 184fh
		mov	bh, 7
		mov	ax, 600h
		int 10h
	endm

numberofoptions	db	0
optionaddresses	dw	8 dup (0)
helpindex	dw	0
helpfilehandle	dw	0
helpsaveds	dw	0
Strange		db	'*** File Disappeared ***'

Returnstackptr	dw	Offset Returnstack
ReturnStack	dw	20 dup (2)

;***************************************************************************
fhelp	proc	near

	cursor	0, 0

	mov	ax, screensegment
	mov	es, ax

	mov	cs:helpsaveds, ds
	call	helpinit		; this will open the file

	call	.help			; while this will do all the help

	call	helpexit		; close the file
	mov	ds, cs:helpsaveds
	ret


fhelp	endP

;***************************************************************************
HFile	db	ordinary_help, 00	; first search on connected
HHFile	db	default_help , 0	; default location if not found

HelpInit	PROC	Near

	push	CS			; initialize the segment
	pop	DS			; operations to take place in CS

	call	HFOpen
	ret

;...........................................................................
HFOpen	PROC	Near
	mov	DX, Offset HFile	; now open the file
	mov	AL, Readonly
	mov	AH, FileOpen
	int	MSDOS
	jnc	HI1
		cmp	AX, 2		; error
		je	Filenotfound
		jmp	DOSERROR
Filenotfound:	mov	DX, Offset HHFile ; try again with default drive
		mov	AL, ReadOnly
		mov	AH, FileOpen
		int	MSDOS
		jnc	HI1
		jmp	DOSERROR

HI1:	mov	CS:HelpFileHandle, AX	; save the filehandle
	ret

DOSconfused	db	'*** Can not open MAX.HLP ***'
DOSError:
	mov	DS, CS:HelpSaveDS
	mov	SI, Offset DOSConfused
	mov	CX, 28
	jmp	.Error0

HFOpen	ENDP

HelpInit	ENDP
;***************************************************************************
.HELP	PROC	Near

	mov	BX, CS:HelpFileHandle	; filehandle
	mov	DX, CS:Helpindex

	call	HSeek			; load it from
	call	HLoad			; our disk

	call	MemSeek			; look for the first 00 00
	cls
	call	HHeader			; get the nodename
	Cursor	3, 0
	call	HScreen			; print the help screen
	call	HOptions		; output the options

ComWait:call	.InCH			; wait for a character to be pressed
	jz	ComWait

	cmp	AL, Exit1
	je	.HelpExit
	cmp	AL, Exit2
	je	.HelpExit
	cmp	AL, Exit3
	je	.HelpExit
	cmp	AL, Backspace
	je	Stackret

	sub	AL, '1'
	cmp	AL, CS:NumberofOptions
	jb	CW1
	call	Sound
	jmp	Comwait

CW1:	xor	AH, AH
	add	AL, AL
	mov	BX, AX
	mov	AX, CS:Optionaddresses[BX]

	mov	DI, CS:ReturnStackPtr	; push Nodename
	push	AX
	mov	AX, CS:Helpindex
	mov	CS:[DI], AX
	pop	AX
	add	DI, 2
	mov	CS:ReturnStackPtr, DI

	mov	CS:Helpindex, AX
	jmp	.Help
.HelpExit:
	mov	ax, 7*256+0		; reinitialize last line
	call	Switchmenu
	call	.CLRMsg			; clear msg area
	jmp	Separatorline		; and rebuild separatorline

Stackret:
	mov	DI, CS:ReturnStackPtr
	sub	DI, 2
	mov	CS:ReturnStackPtr, DI		; pop Nodename

	cmp	DI, Offset ReturnStack		; underflow
	jb	.HelpExit

	mov	AX, CS:[DI]
	mov	CS:Helpindex, AX
	jmp	.Help
	
;...........................................................................
HSeek	PROC	Near
	sub	CX, CX
	mov	AL, 0
	mov	AH, 42h
	int	MSDOS
	ret
HSeek	ENDP

;...........................................................................
HLoad	PROC	Near
	mov	DX, Offset LastLabel	; make it easy
	mov	CX, 2150		; can find it within 2000 bytes
	mov	AH, 3Fh			; and load it
	int	MSDOS
	ret
HLoad	ENDP

.Help	ENDP
;---------------------------------------------------------------------------

Memseek	PROC	Near
	mov	AL, NUL
	mov	SI, (Offset LastLabel)-1
	mov	CX, 2150

MSLoop:	inc	SI
	cmp	Byte Ptr CS:[SI], Newpage
	loopne	MSLoop
	inc	SI				; step over the ^L
	ret

Memseek	ENDP
;---------------------------------------------------------------------------
HHeader	PROC	Near
	cmp	Byte Ptr CS:[SI], NUL
	jnz	HH1
	mov	SI, Offset Strange
	mov	CX, 24
	call	.Msg
	call	Sound
	jmp	HelpExit
HH1:	mov	DI, 2*(160+25)

HHL:	mov	AL, CS:[SI]		; take a character from nodename
	cmp	AL, NUL
	je	EndOfName
	inc	SI
	mov	AH, modelinecolor	; and put it to the screen
	mov	ES:[DI], AX
	add	DI, 2
	jmp	HHL
EndofName:
	ret
HHeader	ENDP
;---------------------------------------------------------------------------
HScreen	PROC	Near
	mov	DX, SI			; output the node
	mov	AH, 9
	int	MSDOS

HS1:	mov	DL, CS:[SI]		; now search for the end of the text
	inc	SI
	cmp	DL, '$'
	jne	HS1
	ret
HScreen	ENDP
;---------------------------------------------------------------------------
HOptions	PROC	NEAR
	cmp	Byte Ptr DS:[SI], NUL
	je	NoOptions

	mov	DI, 23*160		; put it to screen
	cursor	24, 0

	mov	BX, Offset OptionAddresses
	mov	DX, 0

Nextoption:
	inc	DX			; BX incremented in addresspreserve
	call	AddressPreserve
	call	ChoicePrint
	call	OptPrint
	cmp	Byte Ptr DS:[SI], NUL	; a double NUL ends everything
	jne	Nextoption
	mov	CS:NumberofOptions, DL
	ret
Nooptions:
	mov	CS:NumberofOptions, 0
	ret

;...........................................................................
AddressPreserve	PROC	Near

	push	CX
	mov	AL, CS:[SI]		; calculate first 8 bit
	inc	SI
	call	Get16
	mov	CH, AL

	mov	AL, CS:[SI]
	inc	SI
	call	Get8
	add	CH, AL

	mov	AL, CS:[SI]
	inc	SI
	call	Get16
	mov	CL, AL

	mov	AL, CS:[SI]
	inc	SI
	call	Get8
	add	CL, AL

	mov	CS:[BX], CX
	add	BX, 2
	pop	CX
	ret

Get8	PROC	Near		; convert an ASCII to the less significant
	cmp	AL, 'A'		; 4 bits of the AL register
	jae	Get8Ch
	sub	AL, '0'		; '0' -> 0
	ret
Get8Ch:	sub	AL, 'A'-10	; 'A' -> A
	ret
Get8	ENDP

Get16	PROC	Near
	call	Get8		; put the number as a lower 8 bit
	shl	AL, 1		; and put it to the higher one
	shl	AL, 1
	shl	AL, 1
	shl	AL, 1
	ret
Get16	ENDP
AddressPreserve	ENDP	

ChoicePrint	PROC	Near
	mov	Word Ptr ES:[DI], 20
	add	DI, 2
	mov	Word Ptr ES:[DI], 'F'+modelinecolor*256
	add	DI, 2
	mov	DH, modelinecolor
	add	DL, '0'
	mov	Word Ptr ES:[DI], DX	; the number of the function
	sub	DL, '0'
	add	DI, 2
	mov	Word Ptr ES:[DI], '='+modelinecolor*256
	add	DI, 2
	ret
ChoicePrint	ENDP

OptPrint	PROC	NEAR
	mov	AL, CS:[SI]
	inc	SI
	cmp	AL, 0
	je	EndOption
	mov	AH, nocolor
	mov	ES:[DI], AX
	add	DI, 2
	jmp	OptPrint
EndOption:
	ret

OptPrint	ENDP

HOptions	ENDP

HelpExit	PROC	Near
	mov	BX, CS:HelpFileHandle
	mov	AH, FileClose
	int	MSDOS
	mov	CS:HelpIndex, 0
	mov	DI, 23*160
	mov	AX, nocolor*256+' '
	mov	CX, 79
	rep	stosw
	mov	CS:ReturnStackPtr, Offset ReturnStack	; to reenter for DEL
	ret
HelpExit	ENDP

	PROGRAM	ENDS
END


