PUBLIC  FModeline

EXTRN   $Wait:Word, .?Col:Near, .CLRMsg:Near, ActiveWindow:Byte
EXTRN	ActiveBuffer:Byte, Macrodefinition:Byte

;---------------------------------------------------------------------------
TITLE Modeline Updater

	; This routine builds the modeline to the screen. It is very ugly,
	; and should be rewritten, but it works. There are many screenpokes
	; in this routine, but fairly obvious and easy to change. [SCREEN]



Program SEGMENT PARA    PUBLIC  'code'
        ASSUME  CS:Program, DS:Program, ES:Program, SS:Program


	INCLUDE FDEF.DEF

MS_FN	MACRO	Fun
	mov	AH, Fun
	int	21h
	ENDM

stoschar	MACRO
	call	stoscharacter
	ENDM
	
; takes a number in AL [00-99] and outputs its ASCII representation


Msg1	db	'  [TEXT - '
n1	equ	10
SMsg1	db	'  [WRAP - '
sn1	equ	10
Msg2	db	':  '
n2	equ	3
Msg3	db	']  '
n3	equ	3
Msg4	db	'S='
n4	equ	2
Msg5	db	'K  COL '
n5	equ	7
Msg6	db	'   --'
n6	equ	5
Msg7	db	'%--'
n7	equ	3

Msg11	db	'DEF -'
n11	equ	5

Months  db      'JanFebMarAprMayJunJulAugSepOctNovDec'

Newtime	dw	0
Nt	db	0
Oldtime	db	0

EntryStackptr	dw	0
;---------------------------------------------------------------------------
FModeline       PROC    Near

	cld

	MS_FN   2Ch			; an update is necessary every second
	mov	CS:Newtime, CX
	mov	CS:Nt, DH
	cmp	DH, CS:Oldtime		; if the old seconds are the same as
	jne	Update			; the new seconds, no update is nece.
	ret


Update:	dec     CS:$Wait		; if n secs are over clear modeline
	jnz     MWrite
	call    .ClrMsg


MWrite:	mov	CS:EntryStackptr, SP
	mov	AX, Screensegment		; print to the screen segment
	mov	ES, AX
	mov	DI, ModelineStart
;----------
	call	.?Textmode
;----------
	call	.?inMacro
;----------
					; put the buffer name to screen
	mov	AL, 'B'
	stoschar

	mov	AL, CS:ActiveBuffer
	add	AL, '1'
	stoschar

	mov	AL, '-'
	stoschar

	mov	AL, 'W'
	stoschar

	mov	AL, CS:ActiveWindow
	add	AL, '1'
	stoschar

;---------
	mov	SI, Offset Msg2		; put the ':  '
	mov	CX, n2
	call	Modelinetext
;----------
	mov	SI, Offset BCB.File	; now put the filename
	call	ASCIIZText
;----------
	mov	SI, Offset Msg3		; put up some messages
	mov	CX, n3
	call	ModelineText
;--------------------

	MS_FN   2Ah			; now put up the date

	mov     BL, DH			; month is in DH
	add     BL, DH
	add     BL, DH			; BX:=3*months
	xor     BH, BH

	push	dx
	mov	AL, CS:[BX+Offset Months-3]	; and tranlate from table
	stoschar

	mov	AL, CS:[BX+Offset Months-2]
	stoschar				; *E
	mov	AL, CS:[BX+Offset Months-1]
	stoschar				; *E

	mov	AL, ' '
	stoschar
	pop	DX

	mov	AL, DL
	call	Hex8Asc

	mov	AL, ' '
	stoschar
	stoschar

;---------------------
; change Modeline time

	mov	AL, Byte Ptr CS:Newtime+1
	call	Hex8Asc				; hours

	mov	AL, ':'
	stoschar

	mov	AL, Byte Ptr CS:Newtime
	call	Hex8Asc				; minutes

	mov	AL, ':'
	stoschar

	mov	AL, CS:Nt
	mov	CS:Oldtime, AL
	call	Hex8Asc				; seconds

;--------------------
						; Length of File
	mov	AL, ' '
	stoschar
	stoschar
	mov	SI, Offset Msg4
	mov	CX, n4
	call	ModelineText

	mov	AL, ' '
	stoschar

        mov     CX, DS:BCB.FEnd
        sub     CX, 100h
        shr     CH, 1
        shr     CH, 1           		; V : 0..63

	mov	AL, CH
	call	Hex8Asc


;-------------------
	mov	SI, Offset Msg5			; Print the cursor column now
	mov	CX, n5
	call	ModelineText

	push    DI				; find the cursor's column
	call    .?Col
	pop     DI

	mov     AX, DS:BCB.FCurCol		; should have been calculated
	cmp	AX, 999
	jbe	PMCorr
	xor	AX, AX


PMCorr: mov     CL, 100d                ; 1) divide by 100 ( assumes <999 )
	div     CL                      ; divide 0000NNNNh by 10000d
	push	AX
	add     AL, 30h                 ; adjust to Ascii representation
        stoschar
	pop	AX

	mov	AL, AH
        aam                             ; divide by 100 -> DIV in AH, MOD in AL
        xchg    AL, AH
	push	AX
        add     AL, 30h
        stoschar
	pop	AX
        mov     AL, AH
        add     AL, 30h
        stoschar

;-------------------
	mov	SI, Offset Msg6		; change Percent in File
	mov	CX, 6
	call	ModeLineText		; "--"

        mov     AX, DS:BCB.FCursor      ; DS:BCB.FCursor
        sub     AX, 100h
        mov     CX, 100                 ; Multiply by 100 for percent
        mul     CX
        mov     CX, DS:BCB.FEnd
        sub     CX, 100h                ; FileLength
        cmp     CX, 0
        je      Zerodiv
        div     CX
	mov	Word Ptr ES:[DI-2], ' '+Modelinecolor*256
	mov	AH, modelinecolor
	cmp	AL, 100
	je	PTop
	; pass AL
	call	Hex8Asc			; AL:=(Cursor*100)/Length
	jmp	Clearrest

PTop:	mov	AL, '1'			; AL = 100%
	stoschar
	mov	AL, '0'
	stoschar
	mov	AL, '0'
	stoschar
	jmp	Clearrest

ZeroDiv:mov	AL, '-'			; AL = 0 %
	stoschar

ClearRest:
	mov	SI, Offset Msg7
	mov	CX, n7
	call	Modelinetext
	mov	AX, ' '
ClearRest1:				; this will clean the rest
	stoschar			; of our modeline
	jmp	ClearRest1

;***************************************************************************
.?InMacro	PROC	NEAR
	cmp	CS:Macrodefinition, TRUE
	je	.?In1
	ret
.?In1:	mov	SI, Offset Msg11
	mov	CX, n11
	jmp	Modelinetext

.?InMacro	ENDP

FModeline       ENDP

;---------------------------------------------------------------------------
Hex8Asc	PROC	NEAR

        xor     AH, AH
                                        ; number 0..99

					; now the number is in the range 0..99
					; now we can use the AAM instruction !
	aam				; divide by 100-> DIV in AH, MOD in AL
	xchg    AH, AL
	add     AL, '0'

	push	AX
	stoschar		; *E
	pop	AX

	mov     AL, AH
	add     AL, '0'
	stoschar
	ret

Hex8Asc	ENDP
;---------------------
ModeLineText	PROC	NEAR
	mov	AL, CS:[SI]
	inc	SI
	stoschar
	loop	ModelineText
	ret
ModeLineText	ENDP

ASCIIZText	PROC	NEAR
	mov	AL, DS:[SI]
	inc	SI
	cmp	AL, 0
	je	ASCIIZEnd
	stoschar
	jmp	ASCIIZText
ASCIIZEnd:
	ret

ASCIIZText	ENDP
;--------------------
.?textMode	PROC	NEAR
	test	DS:BCB.EDMode, Wrapmode
	jnz	Putwrap

	mov	SI, Offset Msg1		; put '[TEXT - B' to scr
.?T1:	cmp	DS:BCB.Dirty, TRUE
	jne	DSpace
	mov	Byte Ptr CS:[SI+1], '*'
	jmp	DM
DSpace:	mov	Byte Ptr CS:[SI+1], ' '
DM:	mov	CX, n1			; and add a space at the end
	mov	AH, modelinecolor
	jmp	ModeLineText

PutWrap:mov	SI, Offset SMsg1
	jmp	.?T1

.?TextMode	ENDP

;***************************************************************************
Stoscharacter	PROC	NEAR
	cmp	DI, ModeLineEnd
	jae	Exit
	push	ax
	pop	ax
	mov	AH, modelinecolor
	if color			; even though this should be noflicker
	push	AX			; here we can sacrifice enough time
	push	DX			; to update flickerfree
	mov	dx, 3dah
Wait:	in	al, dx
	test	al, 8
	jz	Wait
	pop	DX
	pop	AX
endif
	stosw
	ret

Exit:	mov	SP, CS:EntryStackptr
	ret
Stoscharacter	ENDP
;***************************************************************************
Comment $ The following turns out to turn off the screen for too long
enablescreen	proc	near
	mov	dx, 3D8h
	mov	al, 00000101b
	out	dx, al
	ret
enablescreen	endp

disablescreen	proc	near
	mov	dx, 3dah		; wait until we can disable the screen
Wait1:	in	al, dx
	test	al, 8
	jz	Wait1
	mov	dx, 3D8h		; and disable it
	mov	al, 00001101b
	out	dx, al
	ret
disablescreen	endp
$
        PROGRAM ENDS
END


