%pagesize 77,132

; Title		: SEE
; Version	: 1.1
; Date		: Feb 15, 2000
; Author	: J.R. Ferguson, Amsterdam, the Netherlands
; Download	: http://hello.to/ferguson
; E-mail	: j.r.ferguson@iname.com
; Language	: Intel 8068/8088 assembler
; O.S.		: MS-DOS v3.2
; Hardware	: IBM-PC compatible CGA/EGA/VGA screen
; Assembler	: Borland Turbo Assembler v1.0
; Usage		: SEE filespec
; Function	: Browse textfile
; Description	: in file SEE.TXT

;global register usage:
;	si	offset in textbuffer

	ideal
	dosseg
	model	tiny

false	=	0
true	=	not false

; defaults
dflwst	=	true		;wordstar document adaptions
dfltab	=	true		;tab expansie
dflctr	=	false		;display control characters
dflnum	=	false		;line numbers
dflupc	=	false		;upper case translation in Find command
dflhex	=	false		;hexadecimal display mode

; constants
paglen	=	24		;lines per page, not including prompt line
txtlen	=	79		;characters per line
prmlen	=	79		;characters in prompt line
sidlen	=	16		;number of positions for sideways shift
numlen	=	5		;line number field length
maxlin	=	255		;max length printable line
stksiz	=	128		;stack size in bytes
maxovf	=	256		;max overflow length (in text display mode)

%newpage
; special characters
bs	=	08h		;backspace
can	=	18h		;cancel
clf	=	08h		;move cursor left
cr	=	0dh		;carriage return
eofchr	=	1ah		;end-of-file character
escape	=	1bh		;escape
ff	=	0ch		;form feed
lf	=	0ah		;line feed
tab	=	09h		;horizontal tabulation
white	=	0dbh		;white block

; extended keycodes
KeyIns	=	52h + 80h
KeyEnd	=	4fh + 80h
KeyDown	=	50h + 80h
KeyPgDn	=	51h + 80h
KeyLft	=	4bh + 80h
KeyRgt	=	4dh + 80h
KeyHome	=	47h + 80h
KeyUp	=	48h + 80h
KeyPgUp	=	49h + 80h
KeyIns	=	52h + 80h
KeyDel	=	53h + 80h
KeyF01	=	3Bh + 80h


%newpage
;
; Status masks
;

; cmdsta: command status
ctrmsk	=	00000001b	;control
nummsk	=	00000010b	;line numbers
wstmsk	=	00000100b	;Wordstar
tabmsk	=	00001000b	;tab expansion
upcmsk	=	00010000b	;upper case Find
hexmsk	=	00100000b	;hexadecimal display

; bufsta: buffer status
opnmsk	=	00000001b	;file open
bflmsk	=	00000010b	;start of file
eflmsk	=	00000100b	;end of file
bbfmsk	=	00001000b	;start of buffer
ebfmsk	=	00010000b	;end of buffer
elnmsk	=	00100000b	;end of line
hcrmsk	=	01000000b	;hex display: CR status
hlfmsk	=	10000000b	;hex display: LF status

dflcmd	=		  dflctr and ctrmsk
dflcmd	=	dflcmd or dflnum and nummsk
dflcmd	=	dflcmd or dflwst and wstmsk
dflcmd	=	dflcmd or dfltab and tabmsk
dflcmd	=	dflcmd or dflupc and upcmsk
dflhex	=	dflcmd or dflhex and hexmsk

%subttl "main program / help"
%newpage
;---------------------------------------------------------------------
; main program
;---------------------------------------------------------------------

	codeseg
	assume	cs:@code, ds:@code, es:@code, ss:@code

;
; Program Segment Prefix
;
	org	0080h
label	cmdarg	byte
	org	0081h
label	fsp	byte

;
; Program start
;

	org	0100h

see:	mov	ax,ds
	mov	es,ax

	call	init
	call	openf
	call	rdbuf
	call	clrscr
	call	newpag
rdcmd:	call	cin
docmd:	mov	di,offset cmdtbl
	test	[byte ptr cmdsta],hexmsk
	jz	docmd1
	mov	di,offset cmdtbx
docmd1:	call	srctbl
	jmp	short rdcmd

error:	call	print				;display error message
exit:	call	closef

	mov	ax,4c00h			;return to operating system
	int	21h

;---------------------------------------------------------------------
; help text [command summary]
;---------------------------------------------------------------------

hlpcmd:	call	clrscr
	mov	dx,offset txhelp
	test	[byte ptr cmdsta],hexmsk
	jz	hlpcm1
	mov	dx,offset txhlpx
hlpcm1:	call	print
	call	prompt
	mov	dx,offset txtts
	call	provl
	call	cin
	push	ax
	call	oldpag
	pop	ax
	pop	bx				;pop return address
	call	clrscr
	call	oldpag
	jmp	docmd

%subttl "initialization"
%newpage
;---------------------------------------------------------------------
; initialization
;---------------------------------------------------------------------

init:	cld					;direction flag: upward
	xor	al,al
	mov	[bufsta],al
	mov	[inpbuf],al
	mov	[inpcnt],al
	mov	[lefmar],al
	mov	[word ptr endtxt],offset txtbuf
	mov	[byte ptr rigmar],txtlen
	mov	[byte ptr maxrig],maxlin - ((numlen+2) and dflnum)
	mov	[byte ptr cmdsta],dflcmd

	call	parse				;parse command argument
	call	getebf				;get end buffer pointer
	mov	[buftop],bx
	call	iniprm				;init prompt line
	jmp	prmcmd

%subttl "open/close file"
%newpage
;---------------------------------------------------------------------
; open/close file
;---------------------------------------------------------------------

;
; open file
;
openf:	mov	si,offset cmdarg
	sub	cx,cx
	mov	cl,[si]
	mov	dx,offset txid
	jcxz	erropn				;no filename

	inc	si
	mov	dx,offset txwild
open1:	lodsb					;wildcards?
	cmp	al,'?'
	je	erropn
	cmp	al,'*'
	je	erropn
	loop	open1

	call	opnseq
	jc	errfnf				;file not found

	mov	di,offset txprm+pixdts		;date/time in prompt line
	call	cpydts

	or	[byte ptr bufsta],opnmsk or bflmsk
	and	[byte ptr bufsta],not eflmsk

	mov	[word ptr bbfofs+0],0		;reset begin buffer offset
	mov	[word ptr bbfofs+2],0
	mov	[word ptr endtxt],offset txtbuf	;reset end of text offset
	mov	[word ptr ovflen],0		;reset buffer overflow
	mov	[word ptr curlin],1		;reset line number
	ret

errfnf:	mov	dx,offset txfile
	call	print
	mov	dx,offset txfnf
erropn:	jmp	error

;
; close file
;
closef:	test	[byte ptr bufsta],opnmsk
	jz	close1
	call	closrd
close1:	and	[byte ptr bufsta],not opnmsk
	ret


%subttl "read buffer"
%newpage
;---------------------------------------------------------------------
; read buffer
;---------------------------------------------------------------------

rdbuf:	mov	di,offset txtbuf
	mov	cx,[ovflen]			;insert any overflow in front
	jcxz	rdbuf1
	mov	si,[endtxt]
	rep	movsb

rdbuf1:	mov	si,di				;si = buffer pointer
	call	rdfile
	jnc	rdbuf2

	or	[byte ptr bufsta],eflmsk	;end of file or read error
	call	chkbbf				;check for empty buffer

rdbuf2:	mov	[endtxt],si
	test	[byte ptr bufsta],eflmsk
	jnz	rdbuf3
	call	rdovf				;locate end of last line
rdbuf3:	call	chkbbf				;check for empty buffer

	mov	bx,[curlin]			;locate start of last line
	mov	[beglin],bx
	mov	si,offset txtbuf

rdbuf4:	call	nxtchr				;repeat	repeat read character
	jz	rdbuf4				;	until end of line
	inc	bx				;	increment line number
	test	[byte ptr bufsta],ebfmsk	;until end of buffer
	jz	rdbuf4
	mov	[endlin],bx

	mov	si,offset txtbuf
	or	[byte ptr bufsta],bbfmsk
	and	[byte ptr bufsta],not ebfmsk
	ret
%newpage
;
; check for empty buffer
;
chkbbf:	cmp	si,offset txtbuf		;buffer empty?
	jz	chkbb1
	ret					;  no : ok

chkbb1:	test	[byte ptr bufsta],bflmsk	;  yes: start of file?
	jnz	erremp				;	yes: file is empty
	mov	si,[endtxt]			;	no : to end of buffer
	jmp	gtoebf

erremp:	mov	dx,offset txfile
	call	print
	mov	dx,offset txleeg
	jmp	error

;
; set [endtxt] to end of last line
; set [ovflen] to buffer overflow length
;
rdovf:	push	si
	mov	si,[endtxt]

	test	[byte ptr cmdsta],hexmsk
	jnz	rdovf2

	;Tekst weergave
	mov	bx,si
	sub	bx,maxovf			;bx= lower boundary
	cmp	bx,offset txtbuf
	jnb	rdovf1
	mov	bx,offset txtbuf

rdovf1:	cmp	si,bx
	jb	rdovfX
	call	prvchr				;locate end of last line
	jz	rdovf1
	call	nxtchr				;skip newln
	jmp	short rdovfY

	;Hexadecimal display
rdovf2:	mov	bx,si
	sub	bx,offset txtbuf
	and	bx,000Fh
	sub	si,bx
	jmp	short rdovfY

rdovfX:	mov	si,[endtxt]
rdovfY:	mov	bx,[endtxt]
	mov	[endtxt],si
	sub	bx,si
	mov	[ovflen],bx

	pop	si
	ret

%subttl "next/previous line"
%newpage
;---------------------------------------------------------------------
; previous line
;---------------------------------------------------------------------

linup:	test	[byte ptr bufsta],bbfmsk
	jnz	regup1

	mov	cx,1
	call	backwd
	push	[word ptr curlin]
	push	si
	mov	cx,paglen
	call	backwd
	call	scroll
	call	curhom
	call	nxtlin
	pop	si
	pop	[word ptr curlin]
	call	prompt

regup1:	ret

;---------------------------------------------------------------------
; next line
;---------------------------------------------------------------------

lindn:	test	[byte ptr bufsta],ebfmsk
	jnz	regdn1

	and	[byte ptr bufsta],not bbfmsk
	call	return
	call	nxtlin
	call	prompt

regdn1:	ret

%subttl "page up/down"
%newpage
;---------------------------------------------------------------------
; page up
;---------------------------------------------------------------------

pagup:	test	[byte ptr bufsta],bbfmsk
	jnz	pagup1

	mov	cx,paglen
	call	goback

pagup1:	ret

;---------------------------------------------------------------------
; page down (text display mode)
;---------------------------------------------------------------------

pagdn:	test	[byte ptr bufsta],ebfmsk
	jnz	pagdn1

	mov	bx,[endlin]			;another full page?
	sub	bx,[curlin]
	cmp	bx,paglen
	jb	gtoebf				; no: to end of buffer

	and	[byte ptr bufsta],not bbfmsk
	call	newpag

pagdn1:	ret

;---------------------------------------------------------------------
; page down (hexadecimal display mode)
;---------------------------------------------------------------------

pagdx:	test	[byte ptr bufsta],ebfmsk
	jnz	pagdx1

	mov	bx,[endtxt]			;another full page?
	sub	bx,paglen * 16
	cmp	si,bx
	ja	gtoebf				; no: to end of buffer

	and	[byte ptr bufsta],not bbfmsk
	call	newpag

pagdx1:	ret

%subttl "go to begin/end/next buffer or to start of file
%newpage
;---------------------------------------------------------------------
; go to begin buffer, display page
;---------------------------------------------------------------------

gtobbf:	test	[byte ptr bufsta],bbfmsk
	jnz	gtobb1

gtobb0:	or	[byte ptr bufsta],bbfmsk
	mov	si,offset txtbuf
	mov	bx,[beglin]
	mov	[curlin],bx
	call	newpag

gtobb1:	ret

;---------------------------------------------------------------------
; go to end of buffer
;---------------------------------------------------------------------

gtoebf:	test	[byte ptr bufsta],ebfmsk
	jnz	gtoeb1

	mov	si,[endtxt]
	mov	bx,[endlin]
	mov	[curlin],bx
	call	oldpag

gtoeb1:	ret

;---------------------------------------------------------------------
; go to start of file
;---------------------------------------------------------------------

gtobfl:	test	[byte ptr bufsta],bflmsk
	jnz	gtobbf

gtobf0:	mov	dx,offset txbfl
	call	provl
	call	closef
	call	openf
	call	rdbuf
	jmp	newpag

;---------------------------------------------------------------------
; next buffer
;---------------------------------------------------------------------

nxtbuf:	test	[byte ptr bufsta],eflmsk
	jnz	nxtbu1

	mov	ax,[endtxt]		;adjust buffer start offset
	sub	ax,offset txtbuf
	add	[word ptr bbfofs+0],ax
	adc	[word ptr bbfofs+2],0
	mov	dx,offset txnxbf
	call	provl
	mov	bx,[endlin]
	mov	[curlin],bx
	and	[byte ptr bufsta],not bflmsk
	call	rdbuf
	call	newpag
nxtbu1:	ret

%subttl "locate line number"
%newpage
;---------------------------------------------------------------------
; locate line number
;---------------------------------------------------------------------

gtolin:	call	getlin
	jnz	gtoln1
	jmp	prompt				;empty string : redisplay prompt

gtoln1:	mov	cx,ax
	sub	cx,[curlin]
	inc	cx
	ja	gtoln2
	jb	gtoprv
	jmp	prompt				;we are there already

gtoln2:	test	[byte ptr bufsta],ebfmsk
	jz	gtoln3
	jmp	prompt
gtoln3:	jmp	forwrd				;forward

gtoprv:	test	[byte ptr bufsta],bbfmsk
	jz	gtopr1
	jmp	prompt
gtopr1:	neg	cx				;backward
	jmp	goback

%subttl "find text"
%newpage
;---------------------------------------------------------------------
; find text with upper case translation
;---------------------------------------------------------------------

findu:	or	[byte ptr cmdsta],upcmsk
	jmp	short find1

;---------------------------------------------------------------------
; find same text again
;---------------------------------------------------------------------

findx:	call	oldtxt
	jmp	short find2

;---------------------------------------------------------------------
; find literal text
;---------------------------------------------------------------------

find:	and	[byte ptr cmdsta],not upcmsk
find1:	call	gettxt
find2:	jz	find3				;empty string : redisplay prompt
	test	[byte ptr bufsta],ebfmsk
	jnz	find3

	call	srctxt
	inc	[word ptr curlin]
	jmp	oldpag

find3:	jmp	prompt

;
; find string in current buffer, starting at current line
; [tab en newline are seen as spaces]
;
; in:	bx	string offset
;	ch	string length
;
srctxt:	call	srcnxt
	jnz	srctx2

	test	[byte ptr bufsta],elnmsk
	jz	srctx1
	inc	[word ptr curlin]

srctx1:	cmp	al,[bx]
	jnz	srctxt
	call	srcrst
	jnz	srctxt

srctx2:	ret

%newpage
;
; search remainder of string
;
; in:	bx	string offset
;	ch	string length
; out:	z-flag	nz = no match, z = match found, or end of buffer
;	ch,bx	unchanged
;
srcrst:	push	bx				;check remainder of string
	push	cx
	push	si
	jmp	short srcrs2
srcrs1:	call	srcnxt
	jnz	srcrs3
	cmp	al,[bx]
	jnz	srcrs4
srcrs2:	inc	bx
	dec	ch
	jnz	srcrs1
srcrs3:	cmp	al,al				;match or end of buffer: z=1
srcrs4:	pop	si
	pop	cx
	pop	bx
	ret

; Find next character
; upper case conversion if upcbit=1
; tab and newline are seen as spaces
;
; out:	z-flag			nz : end of buffer
;	bufsta and elnmsk	nz : end of line
;	al			character
;
srcnxt:	call	nxtchr
	jnz	srcnx1
	call	cndupc
	cmp	al,tab
	jnz	srcnx2
srcnx1:	mov	al,' '
srcnx2:	test	[byte ptr bufsta],ebfmsk
	ret

%subttl "scroll left/right"
%newpage
;---------------------------------------------------------------------
; scroll sidlen positions to the right
;---------------------------------------------------------------------

posrig:	mov	al,[maxrig]			;right margin = maxrig ?
	sub	al,[rigmar]
	jz	posri1

	mov	ch,sidlen
	call	minim				;offs=min(sidlen,maxrig-rigmar)
	add	[rigmar],ch			;right margin += offset
	add	[lefmar],ch			;left margin  += offset
	call	oldpag

posri1:	ret

;---------------------------------------------------------------------
; scroll sidlen positions to the left
;---------------------------------------------------------------------

poslef:	mov	al,[lefmar]			;left margin = 0?
	and	al,al
	jz	posle1				;  yes: return

	mov	ch,sidlen
	call	minim				;offs=min(sidlen,left margin)
	sub	[lefmar],ch			;left margin  -= offs
	sub	[rigmar],ch			;right margin -= offs
	call	oldpag

posle1:	ret

;---------------------------------------------------------------------
; scroll max left (text display mode)
;---------------------------------------------------------------------

paglef:	mov	al,[lefmar]			;left margin = 0?
	and	al,al
	jz	pagle1				;  yes: return

	sub	[rigmar],al			;right margin -= left margin
	mov	[byte ptr lefmar],0		;left margin = 0

	call	oldpag
pagle1:	ret

%subttl "display page"
%newpage
;---------------------------------------------------------------------
; display page
;---------------------------------------------------------------------

oldpag:	and	[byte ptr bufsta],not (hcrmsk or hlfmsk)
	mov	cx,paglen
	call	backwd

newpag:	and	[byte ptr bufsta],not (hcrmsk or hlfmsk)
	call	curhom
	mov	cx,paglen
newpa1:	push	cx
	call	nxtlin
	pop	cx
	test	[byte ptr bufsta],ebfmsk
	jnz	newpa2
	loop	newpa1
newpa2:	call	clreos
	jmp	prompt

;---------------------------------------------------------------------
; display line (text display mode)
;---------------------------------------------------------------------

nxtlin:	test	[byte ptr cmdsta],hexmsk	;check hex display
	jnz	hexlin

	mov	[byte ptr chrcnt],0

	test	[byte ptr cmdsta],nummsk	;display line number
	jz	nxtln1
	mov	ax,[curlin]
	call	decout

nxtln1:	call	nxtchr				;display text
	jnz	nxtln2
	call	dochr
	jmp	short nxtln1

nxtln2:	inc	[word ptr curlin]
	jmp	newln

%newpage
;---------------------------------------------------------------------
; display line (hexadecimal display mode)
;---------------------------------------------------------------------

hexlin:	call	dmpofs				;start offset
	call	nxthln				;read 16 bytes max
	call	dmphex				;hex dump
	call	dmpasc				;ASCII dump
	call	newln
	cmp	si,[endtxt]
	jb	hexln1
	or	[byte ptr bufsta],ebfmsk
hexln1:	ret

;---------------------------------------------------------------------
; fill hex line buffer
;---------------------------------------------------------------------
nxthln:	mov	di,offset hexbuf
	mov	[word ptr hexcnt],0
	mov	cx,16
nxthl1:	call	nxtchr
	jz	nxthl2
	inc	[word ptr curlin]
nxthl2:	test	[byte ptr bufsta],ebfmsk
	jnz	nxthl3
	stosb
	inc	[word ptr hexcnt]
	loop	nxthl1
nxthl3:	ret

;---------------------------------------------------------------------
; display hex line start address (buffer offset)
;---------------------------------------------------------------------
dmpofs:	xor	dx,dx				;dx:ax = file offset
	mov	ax,si
	sub	ax,offset txtbuf
	add	ax,[word ptr bbfofs+0]
	adc	dx,[word ptr bbfofs+2]
	push	ax
	mov	ax,dx
	call	outhxw
	mov	al,' '
	call	cout
	pop	ax
	call	outhxw
	mov	al,':'
	call	cout
	mov	al,' '
	jmp	cout

;---------------------------------------------------------------------
; display hex line dump
;---------------------------------------------------------------------
dmphex:	mov	bl,0			;byte count
	mov	cx,[hexcnt]
	jcxz	dmphx2

	mov	di,offset hexbuf	;hex dump
dmphx1:	mov	al,[di]
	call	outhxb
	call	dmphbl
	inc	di
	loop	dmphx1

dmphx2: cmp	bl,16			;right margin
	jnb	dmphx3
	call	dmphxs
	jmp	short dmphx2
dmphx3:	ret

dmphxs:	mov	al,' '			;space entry in hex dump
	call	cout
	mov	al,' '
	call	cout
	jmp	short dmphbl

%newpage
;
; display word AX hexadecimal (4 digits)
;
outhxw:	push	ax
	mov	al,ah
	call	outhxb
	pop	ax
;;	jmp	short outhxb

;
; display byte AL hexadecimal (2 digits)
;
outhxb:	push	ax
	shr	al,1
	shr	al,1
	shr	al,1
	shr	al,1
	call	outhx1
	pop	ax
outhx1:	and	al,0Fh
	add	al,'0'
	cmp	al,'9'
	jna	outhx2
	add	al,'A'-('9'+1)
outhx2:	jmp	cout

;
; display space in hex dump
; adjust byte count bl bij
; extra space if bl is a multiple of 8
;
dmphbl:	mov	al,' '
	call	cout
	inc	bl
	test	bl,07h
	jnz	dmphb1
	mov	al,' '
	call	cout
dmphb1:	ret

;---------------------------------------------------------------------
; display hex line ASCII
;---------------------------------------------------------------------
dmpasc:	mov	cx,[hexcnt]
	jcxz	dmpas2

	mov	di,offset hexbuf
dmpas1:	mov	al,[di]
	call	outasc
	inc	di
	loop	dmpas1

dmpas2: ret

;
; Display byte ASCII if printable, else '.'
;
outasc:	and	al,7Fh			;remove parity
	cmp	al,' '
	jb	outas1
	cmp	al,'~'
	jna	outas2
outas1:	mov	al,'.'
outas2:	jmp	cout

%subttl "display character"
%newpage
;---------------------------------------------------------------------
; display character
;---------------------------------------------------------------------

dochr:	mov	ah,[cmdsta]
	test	ah,wstmsk			;Wordstar?
	jz	dochr2
	cmp	al,1fh				;  yes:	soft hyphen at end?
	jz	dochr0
	cmp	al,1eh				;	soft hyphen in line?
	jnz	dochr1
	test	ah,ctrmsk
	jnz	dochr0
	ret
dochr0:	mov	al,'-'
	jmp	short outchr
dochr1:	cmp	al,0fh				;	fixed spatie?
	jz	dochr6

dochr2:	cmp	al,tab				;tab?
	jnz	dochr7
	test	ah,tabmsk			;  yes: tab expansion?
	jz	dochr5				;	no : print space/^i

dochr3:	call	dochr6				;	yes: expand tab
	jz	dochr4
	test	[byte ptr chrcnt],07h
	jnz	dochr3
dochr4:	ret

dochr5:	test	ah,ctrmsk
	jnz	dochrA
dochr6:	mov	al,' '
	jmp	short outchr

dochr7:	cmp	al,7fh
	je	dochr8
	cmp	al,1fh
	ja	outchr

dochr8:	test	ah,ctrmsk			;control character?
	jnz	dochrA
	cmp	al,bs
	jz	dochr9
	ret
dochr9:	mov	al,clf
	jmp	short outchr

dochrA:	push	ax
	mov	al,'^'
	call	outchr
	pop	ax
	add	al,'@'				;make prontable
	and	al,7fh				;del -> ^?
;	jmp	short outchr			;proceed with outchr
%newpage
;
; display character if in window lefmar .. rigmar
; chrcnt is adjusted
;
outchr:	push	bx
	push	cx
	push	dx

	mov	cl,[chrcnt]			;chrcnt = rigmar?
	cmp	cl,[rigmar]
	je	outch2				;  yes: exit

	cmp	al,clf				;chr = cursor left?
	jne	outch1				;  no
	and	cl,cl				;  yes: chrcnt = 0?
	jz	outch2				;	yes: exit
	dec	cl				;	no : backward 1
	dec	cl

outch1:	inc	cl				;chrcnt += 1
	mov	[chrcnt],cl
	cmp	cl,[lefmar]			;chrcnt <= lefmar?
	jna	outch2				;  yes: exit
	call	conout				;  no : display chr

outch2:	pop	dx
	pop	cx
	pop	bx
	ret

%subttl "prompt line"
%newpage
;---------------------------------------------------------------------
; prompt line
;---------------------------------------------------------------------

;prompt line format :
;0         1         2         3         4         5         6         7
;0123456789012345678901234567890123456789012345678901234567890123456789012345678
;#[]#ctw#filename.ext#yyyy-mm-dd#hh:mm:ss#######################esc=stop#?=help#
; <> CTW              prompt overlay [+ input buffer]
;    HEX

pixbeg	=	1
pixend	=	2
pixhex  =       4
pixctr	=	4
pixtab	=	5
pixwst	=	6
pixfsp	=	8
pixovl	=	21
pixdts	=	21
pixstp	=	63
pixhlp	=	72
inplen	=	prmlen - (pixovl+6) - 1

;
; display prompt line
;
prompt:	call	prmbuf				;adjust begin/end markers
	call	endpag
	mov	dx,offset txprm
	call	print
	jmp	return

;
; display prompt overlaytext af
; in :	dx	offset text (0-ended)
;
provl:	push	cx
	push	dx
	mov	dh,paglen			;wipe old overlay
	mov	dl,pixovl
	call	setcur
	mov	cx,(prmlen-1)-pixovl
	mov	al,white
provl1:	call	cout
	loop	provl1
	mov	dh,paglen			;display new overlay
	mov	dl,pixovl
	call	setcur
	pop	dx
	call	print
	pop	cx
	ret

%newpage
;---------------------------------------------------------------------
; init prompt line
;---------------------------------------------------------------------

iniprm:	mov	di,offset txprm
	mov	al,white			;white line
	mov	cx,prmlen
	rep	stosb
	xor	al,al				;end-of-string marker
	stosb

	mov	di,offset txprm+pixfsp		;filespec
	call	cpyfsp

	mov	si,offset txpstp		;'esc=stop'
	mov	di,offset txprm+pixstp
	mov	cx,lnpstp
	rep	movsb

	mov	si,offset txphlp		;'?=help'
	mov	di,offset txprm+pixhlp
	mov	cx,lnphlp
	rep	movsb

	ret

%newpage
;---------------------------------------------------------------------
; adjust stel prompt line
;---------------------------------------------------------------------

;
; begin/end markers
;
prmbuf:	mov	ah,[bufsta]
	mov	al,white				;begin marker
	test	ah,bbfmsk
	jz	prmbu1
	mov	al,'<'
	test	ah,bflmsk
	jz	prmbu1
	mov	al,'['
prmbu1:	mov	[txprm+pixbeg],al

	mov	al,white				;end marker
	test	ah,ebfmsk
	jz	prmbu2
	mov	al,'>'
	test	ah,eflmsk
	jz	prmbu2
	mov	al,']'
prmbu2:	mov	[txprm+pixend],al
	ret

;
; command toggles
;
prmcmd:	mov	ah,[cmdsta]
	test	ah,hexmsk			;hexadecimal display
	jnz	prmhex

	mov	al,'c'				;control
	test	ah,ctrmsk
	jz	prmcm1
	call	upcase
prmcm1:	mov	[txprm+pixctr],al

	mov	al,'t'				;tab expansion
	test	ah,tabmsk
	jz	prmcm2
	call	upcase
prmcm2:	mov	[txprm+pixtab],al

	mov	al,'w'				;Wordstar document
	test	ah,wstmsk
	jz	prmcm3
	call	upcase
prmcm3:	mov	[txprm+pixwst],al
	ret

prmhex:	push	si
	mov	si,offset txhex
	mov	di,offset txprm+pixhex
	mov	cx,lnhex
	rep	movsb
	pop	si
	ret

%subttl "forward/backward within buffer"
%newpage
;---------------------------------------------------------------------
; forward/backward within buffer
;---------------------------------------------------------------------

;
; go cx lines forward within buffer and display page
;
forwrd:	test	[byte ptr bufsta],ebfmsk
	jnz	forwd1
	call	nxtchr
	jz	forwrd
	inc	[word ptr curlin]
	loop	forwrd
forwd1:	jmp	oldpag

;---------------------------------------------------------------------
; backward within buffer
;---------------------------------------------------------------------

;
; go cx lines backward within buffer and display page
;
goback:	call	backwd
	jmp	oldpag

;
; go cx lines backward within buffer
; but no further then to start of buffer
;
backwd:	test	[byte ptr cmdsta],hexmsk
	jnz	hbackw
	call	prvlin
	dec	[word ptr curlin]
	test	[byte ptr bufsta],bbfmsk
	loopz	backwd
	ret

; previous line
prvlin:	call	prvchr				;skip newline backward
prvln1:	call	prvchr				;skip to newline backward
	jz	prvln1
	test	[byte ptr bufsta],bbfmsk	;start of buffer ?
	jnz	prvln2
	call	nxtchr				;  no : skip newline forward
prvln2:	ret

;
; hex display: backward cx lines of max 16 bytes each
; but no further then to start of buffer
; (last buffer line may have less than 16 bytes)
;
hbackw:	push	cx
	mov	cx,si				;last line may be < 16 byte
	sub	cx,offset txtbuf
	and	cx,000Fh
	jnz	hback1
	mov	cx,16
hback1:	call	prvchr
	test	[byte ptr bufsta],elnmsk
	jz	hback2
	dec	[word ptr curlin]
hback2:	test	[byte ptr bufsta],bbfmsk
	loopz	hback1
	pop	cx
	loopz	hbackw
	cmp	si,offset txtbuf
	jnz	hback3
	or	[byte ptr bufsta],bbfmsk
hback3:	ret

%newpage
;---------------------------------------------------------------------
; toggle flags
;---------------------------------------------------------------------

;
; line number
;
tognum:	mov	al,numlen+2
	test	[byte ptr cmdsta],nummsk
	jnz	tognu1
	neg     al
tognu1:	add	[rigmar],al
	add	[maxrig],al
	mov	al,nummsk
	jmp	short togcmd

;
; Wordstar document
;
togwst:	mov	al,wstmsk
	jmp	short togcmd

;
; tab expansion
;
togtab:	mov	al,tabmsk
	jmp	short togcmd

;
; display control characters
;
togctr:	mov	al,ctrmsk
;;	jmp	short togcmd

togcmd:	xor	[byte ptr cmdsta],al
	call	prmcmd				;adjust prompt line
	jmp	oldpag

;
; hexadecimal display
;
toghex:	xor	[byte ptr cmdsta],hexmsk
	call	paglef				;scroll max left
	call	prmcmd
	jmp	gtobf0

%subttl "read character forward/backward"
%newpage
;---------------------------------------------------------------------
; read character forward/backward
;---------------------------------------------------------------------

;
; read next/previous character from buffer
;
; in:	si	buffer pointer
; out:	z-flag	nz: newline [cr,lf,cr-lf,lf-cr,ff] or start/end of buffer
;	al	character
;		for newline: CR (not in hex display mode)
;	si	adjusted
;
; bufsta elnmsk         set for newline or start/end of buffer
; bufsta ebfmsk/bbfmsk  set for start/end of buffer
;

;
; forward
;
nxtchr:	push	bx
	push	cx
	push	dx
	and	[byte ptr bufsta],not ebfmsk
	mov	cx,1
	mov	dx,[endtxt]
	call	getchr
	jnz	retchr
	or	[byte ptr bufsta],ebfmsk
	jmp	short retchr

;
; backward
;
prvchr:	push	bx
	push	cx
	push	dx
	and	[byte ptr bufsta],not bbfmsk
	mov	cx,-1
	mov	dx,offset txtbuf-1
	dec	si
	call	getchr
	jnz	prvch1
	or	[byte ptr bufsta],bbfmsk
prvch1:	inc	si
;
; common return
;
retchr:	pop	dx
	pop	cx
	pop	bx
	test	[byte ptr bufsta],elnmsk
	ret

%newpage
;
; read next/previous character
; cr-lf and lf-cr count as 1 character (text display mode only)
;
; in:	cx	1 : next , -1 : previous
;	dx	offset address past start/end of buffer
;	si	buffer pointer
; out:	z-flag	z : past start/end of buffer
;	al	character
;	si	bijgewerkt
;
; changes ah
;
getchr:	test	[byte ptr cmdsta],hexmsk
	jnz	getbyt

	and	[byte ptr bufsta],not elnmsk

	cmp	si,dx				;test start/end of buffer
	jz	gtceln

	mov	al,[si]				;read byte from buffer
	and	al,7fh				;remove parity
	add	si,cx				;adjust buffer pointer
	cmp	al,cr				;end of line?
	jz	gtccr
	cmp	al,lf
	jz	gtclf
	cmp	al,ff
	jz	gtceln
	ret					;  no

gtclf:	mov	ah,cr
	jmp	short gtcskp
gtccr:	mov	ah,lf
gtcskp:	cmp	si,dx				;test start/end of buffer
	jz	gtceln
	mov	al,[si]				;read byte from buffer
	and	al,7fh				;remove parity
	cmp	al,ah
	jnz	gtceln
	add	si,cx

gtceln:	mov	al,cr				;return cr
	or	[byte ptr bufsta],elnmsk
	cmp	si,dx
	ret

%newpage
;
; get byte (like getchr, hexadecimal display mode)
;
getbyt:	push	bx
	mov	ah,[bufsta]				;copy buffer status
	and	ah,not (hcrmsk or hlfmsk or elnmsk)	;reset CR,LF,eln flags

	cmp	si,dx					;past start/end:
	jnz	gtbcr
	test	[byte ptr bufsta],hcrmsk or hlfmsk	; prev chr was CR/LF ?
	jnz	gtbrz
	or	ah,elnmsk				; no : set eln flag
gtbrz:	cmp	cx,cx					;return Z
	jmp	short gtbret

gtbcr:	mov	al,[si]					;read character
	add	si,cx					;adjust buffer pointer
	mov	bl,al					;BL = character
	and	bl,7fh					;     without parity bit
	cmp	bl,cr					;CR
	jnz	gtblf
	test	[byte ptr bufsta],hlfmsk		; prev chr was LF ?
	jnz	gtbrnz
	or	ah,hcrmsk or elnmsk			; no : set CR,eln flag
	jmp	short gtbrnz

gtblf:	cmp	bl,lf					;LF
	jnz	gtbff
	test	[byte ptr bufsta],hcrmsk		; prev chr was CR ?
	jnz	gtbrnz
	or	ah,hlfmsk or elnmsk			; no : set LF,eln flag
	jmp	short gtbrnz

gtbff:	cmp	bl,ff					;FF
	jnz	gtbrnz
	or	ah,elnmsk				; set eln flag

gtbrnz:	and	cx,cx					;return NZ
gtbret:	mov	[bufsta],ah				;set buffer status
	pop	bx
	ret

%subttl "general routines"
%newpage
;---------------------------------------------------------------------
; general routines
;---------------------------------------------------------------------

;
; parse command argument
;
; situation at start    cmdarg:	1 byte length command argument
;				(not including end-of-string mark)
;			fsp:	{ <spate group> <argument> }
;				ending character (ASCII CR)
;
; situation at end	cmdarg:	1 byte length first argument
;				(not including end-of-string mark)
;			fsp:	first argument in capitals
;				end-of-string mark (00h)
;
parse:	mov	si,offset fsp
	mov	di,si
parse0:	lodsb					;skip spaces
	cmp	al,' '
	je	parse0

	sub	cl,cl				;length= 0
parse1:	call	upcase
	cmp	al,' '
	je	parse2
	cmp	al,cr
	je	parse2
	stosb					;copy up to space or CR
	inc	cl				;and adjust length
	lodsb
	jmp	short parse1

parse2:	mov	[byte ptr di],0			;convert into ASCIIZ string
	mov	[byte ptr cmdarg],cl		;and adjust length
	ret

%newpage
;
; copy fsp without drive or path
; in:	di	destination offset
;
cpyfsp:	mov	si,offset cmdarg		;cx= length of full fsp
	xor	cx,cx
	mov	cl,[si]
	jcxz	cpyfs5				;if (cx != 0)
	add	si,cx				;{ si += cx
	std
cpyfs1:	lodsb					;  scan backward
	cmp	al,'\'				;    to '\'
	jz	cpyfs2
	cmp	al,':'				;    or ':'
	loopne	cpyfs1				;    or begin fsp
cpyfs2:	cld
	jne	cpyfs3				;  if ':' or '\'
	inc	si				;    si before start of fsp
cpyfs3:	inc	si				;  copy fsp [di]<-[si]
cpyfs4:	lodsb
	and	al,al
	jz	cpyfs5
	stosb
	jmp	short cpyfs4
cpyfs5:	ret					;}

%newpage
;
; copy file date/time stamp
; in:	di	destination offset
;
cpydts:	call	getdts

	mov	bh,'0'				;leading zero
	mov	bl,4				;4 digits
	sub	ax,ax				;year = (dx bit 9-15) + 1980
	mov	al,dh
	shr	ax,1
	add	ax,1980
	call	stdec
	mov	[byte ptr di],'-'
	inc	di

	mov	bl,2				;2 digits
	mov	ax,dx				;month = dx bit 5-8
	rept	5
	shr	ax,1
	endm
	and	ax,1111b
	call	stdec
	mov	[byte ptr di],'-'
	inc	di

	mov	ax,dx				;day = dx bit 0-4
	and	ax,11111b
	call	stdec
	inc	di

	sub	ax,ax				;hours = cx bit 11-15
	mov	al,ch
	rept	3
	shr	ax,1
	endm
	call	stdec
	mov	[byte ptr di],':'
	inc	di

	mov	ax,cx				;minutes = cx bit 5-10
	rept	5
	shr	ax,1
	endm
	and	ax,111111b
	call	stdec
	mov	[byte ptr di],':'
	inc	di

	mov	ax,cx				;seconds = (cx bit 0-4) * 2
	and	ax,11111b
	shl	ax,1
	call	stdec
	ret

%newpage
;
; store ax decimal
;
; in :	ax	value (unsigned 16 bit integer)
;	bl	number of digits
;	bh	leading zero character
;	di	destination offset
;
; out:	di	incremented to after the last digit
;
stdec:	push	bx
	push	cx
	push	dx
	push	si

	sub	cx,cx				;cx = number of digits
	mov	cl,bl

	push	bx
	push	cx
	mov	si,offset decbuf + 4		;fill digit buffer backward
	mov	bx,10
stdec1:	sub	dx,dx
	div	bx
	mov	[si],dl
	dec	si
	loop	stdec1
	pop	cx
	pop	bx

	inc	si
stdec2:	lodsb					;get digit from buffer
	add	al,'0'				;convert to ASCII
	cmp	al,'0'				;adjust leading zeroes
	jnz	stdec3
	cmp	cx,1
	jz	stdec4
	mov	al,bh
	jmp	short stdec4
stdec3:	mov	bh,'0'
stdec4:	stosb
	loop	stdec2

	pop	si
	pop	dx
	pop	cx
	pop	bx
	ret
%newpage
;
; ch = minimum(al,ch)
minim:	cmp	al,ch
	jnb	minim1
	mov	ch,al
minim1:	ret


;
; find command in table and execute it
;
; in:	al	command character
;	di	start of table
;
srctbl:	call	upcase
	mov	cx,[di]
srctb1:	add	di,2
	scasb
	loopne	srctb1
	jne	srctb2
	jmp	[word ptr di]
srctb2:	ret


;
; convert to upper case if (cmdsta and upcmsk) <> 0
;
; in:	al	character
; out:	al	character
;
cndupc:	test	[byte ptr cmdsta],upcmsk
	jnz	upcase
	ret

;
; convert to upper case
; in :	al	character
; out:	al	character
;
upcase:	cmp	al,'a'
	jb	upcas1
	cmp	al,'z'
	ja	upcas1
	sub	al,'a'-'A'
upcas1:	ret

%newpage
;
; read text from keyboard (upper case if (cmdsta and upcmsk) <> 0)
; out:	bx	start offset text
;	ch	charcter count
;	z-flag	z : empty string
;
gettxt:	call	prfind				;prompt
	mov	dh,' '
	mov	dl,'~'
	call	getstr
	mov	[inpcnt],ch
	ret

;
; retrieve old search text
; out:	bx	start offset text
;	ch	charcter count
;	z-flag	z : empty string
;
oldtxt:	call	prfind				;repeat find prompt
	mov	dx,bx				;repeat find text
	call	print
	mov	ch,[inpcnt]			;get character count
	and	ch,ch				;test for empty string
	ret

;
; display find prompt, regarding (cmdsta and upcmsk)
; and clear the text input field
;
; out:	ch	inplen
;	bx	inpbuf
;
prfind:	mov	dx,offset txtxt
	test	[byte ptr cmdsta],upcmsk
	jz	prfnd1
	mov	dx,offset txtxth
prfnd1:	call	provl
	mov	bx,offset inpbuf
	mov	ch,inplen
	jmp	clrfld

%newpage
; read line number
; out:	ax	line number (unsigned integer)
;	z-flag	z : empty string, 0 or overflow (>65535)
;
;
getlin:	mov	dx,offset txline			;prompt
	call	provl
	mov	ch,numlen
	call	clrfld
	mov	bx,offset numbuf
	mov	dh,'0'
	mov	dl,'9'
	call	getstr
	jz	getln2
;
; convert string [bx] with length ch digits into unsigned integer ax
;
	sub	ax,ax				;init result

getln1: mov	dx,10				;ax <- 10 * ax + digit value
	mul	dx
	jc	getln3				;check overflow
	mov	dl,[bx]
	inc	bx
	sub	dl,'0'
	xor	dh,dh
	add	ax,dx
	jc	getln3				;check overflow
	dec	ch
	jnz	getln1

	and	ax,ax				;test for 0
getln2:	ret					;normal exit

getln3:	cmp	al,al				;error exit : return z
	ret

%newpage
;
; Read cr-ended string consisting of characters within an allowed range.
; Replace tabs by spaces.
; Convert lower case letters to upper case if (cmdsta and upcmsk) <> 0
;
; control keys:
;	bs,KeyDel	delete 1 character
;	can		delete line
;
; in:	ch		max. number of characters [1..inplen]
;	dh		lowest character code allowed
;	dl		highest character code allowed
;	bx		start offset input buffer
; out:	ch		actual character count
;	z-flag	z : empty string
;	bx,dx	unchanged
;
getstr:	push	bx
	mov	cl,ch
	mov	ch,0

gets1:	call	cin				;read key
	call	cndupc				;optional upper case conversion

	cmp	al,cr				;return or enter?
	jz	gets7				;  yes: done

	cmp	al,bs				;backspace, Del or Left?
	jz	gets3
	cmp	al,KeyDel
	jz	gets3
	cmp	al,KeyLft
	jnz	gets4
gets3:	call	delchr				;  yes: delete character
	jmp	short gets1

gets4:	cmp	al,can				;cancel?
	jnz	gets5
	call	cancel				;  yes: delete line
	jmp	short gets1

gets5:	cmp	al,tab				;replace tab by space
	jnz	gets6
	mov	al,' '

gets6:	cmp	al,dh				;out of range?
	jb	gets1				;  yes: discard character
	cmp	al,dl
	ja	gets1

	and	cl,cl				;buffer full?
	jz	gets1				;  yes: discard character

	call	cout
	mov	[bx],al
	inc	bx
	inc	ch
	dec	cl
	jmp	short gets1

gets7:	call	return
	mov	[byte ptr bx],0			;add end-of-string marker
	and	ch,ch				;test for length 0
	pop	bx
	ret
%newpage
;
; delete input line backward
;
cancel:	call	delchr
	jnz	cancel
	ret

;
; delete 1 character backward
;
; out:	Flags	cond z : input buffer empty
;
delchr:	and	ch,ch				;test for empty buffer
	jz	delch2

	dec	bx
	inc	cl
	dec	ch
	call	delch1				;delete previous character
	mov	al,' '
	call	cout
delch1:	mov	al,bs
	call	cout

delch2:	ret

%newpage
;
; go to start of line
;
return:	mov	al,cr
	jmp	cout

;
; delete to end of line and go to next line
;
newln:	call	clreol
	mov	al,cr
;	jmp	short conout

;
; display character to console
; adds lf after cr
;
; in:	al	character
;
conout:	push	bx
	call	cout
	cmp	al,cr
	jnz	conou1
	mov	al,lf
	call	cout
conou1:	pop	bx
	ret

;
; clear ch positions and go back to current position
; leave cx unchanged
;
clrfld:	mov	al,' '
	call	clrfl1
	mov	al,bs
clrfl1:	push	cx
clrfl2:	call	cout
	dec	ch
	jnz	clrfl2
	pop	cx
	ret

%newpage
;
; display unsigned decimal integer
;
; in:	ax	value
;
decout:	mov	dx,offset txlnum
	mov	bl,5				;5 digits
	mov	bh,' '				;leading spaces
	mov	di,dx
	call	stdec
;	jmp	print

;
; display text
; in:	dx	start offset text (with 0 byte as end-of-syting marker)
;
print:	push	si
	mov	si,dx
print1:	lodsb
	and	al,al
	jz	print2
	call	conout
	jmp	short print1
print2:	pop	si
	ret

%subttl "hardware dependant routines"
%newpage
;---------------------------------------------------------------------
; hardware dependant routines (IBM-PC BIOS, CGA/EGA/VGA)
;---------------------------------------------------------------------

;
; clear screen, cursor home
;
clrscr:	push	si
	mov	ax,0003h			;set screen mode CGA 25*80
	int	10h
	pop	si
	ret

;
; cursor home
;
curhom:	mov	dx,0000h			;row 0, column 0
;	jmp	setcur

;
; set cursor position
;
; in :	dh	row	(0 = leftmost column)
;	dl	column	(0 = topmost row)
;
setcur:	push	si
	mov	ah,02h										;set cursor
	mov	bh,00h				;screen 0
	int	10h
	pop	si
	ret

;
; clear to end of text screen
;
clreos:	push	si

	mov	ah,03h				;get cursor position
	mov	bh,00h				;screen 0
	int	10h				;gives dh=row, dl=col

	mov	cx,paglen			;count in cx
	sub	cl,dh
	jcxz	clreos1				;if count > 0
	mov	ax,txtlen+1			;  count= count * (txtlen+1)
	mul	cx
	mov	cx,ax
	mov	ax,0a20h			;  write spaces (leaves cursor)
	mov	bx,0007h			;  screen 0, normal intensity
	int	10h
clreos1:					;endif
	pop	si
	ret

;
; clear to end of line
;
clreol:	push	si

	mov	ah,03h				;get cursor position
	mov	bh,00h				;screen 0
	int	10h				;gives dh=row, dl=col

	mov	cx,txtlen			;count in cx
	sub	cl,dl
	jcxz	clreol1				;if count > 0
	mov	ax,0a20h			;  write spaces (leaves cursor)
	mov	bx,0007h			;  screen 0, normal intensity
	int	10h
clreol1:					;endif
	pop	si
	ret

;
; scroll screen down 1 line
;
scroll:	push	si
	mov	ax,0701h			;scroll down 1 line
	mov	cx,0000h			;upper-left row,col
	mov	dh,paglen-1			;lower-right row
	mov	dl,txtlen-1			;lower-right col
        mov	bh,07h				;normal intensity
	int	10h
	pop	si
	ret

%newpage
;
; set cursor at beginning of prompt line
;
endpag:	push	si
	mov	ah,02h				;set cursor
	mov	bh,0				;screen 0
	mov	dh,paglen			;last row+1
	xor	dl,dl				;column 0
	int	10h
	pop	si
	ret

;
; character input from console
; out:	al	character
;
cin:	push	bx
	mov	ah,00h				;BIOS read keyboard
	int	16h
	and	al,al				;keycode = 0?
	jnz	cin1
	mov	al,ah				;  yes: extended keycode
	add	al,80h				;	+ 80h
cin1:	pop	bx
	ret

;
; character out
; in	al	character
;
cout:	push	ax
	push	bx
	push	si
	mov	ah,0eh				;BIOS character to TTY
	mov	bx,0007h			;screen 0, normal intensuty
	int	10h
	pop	si
	pop	bx
	pop	ax
	ret

%subttl "o.s. dependant routines"
%newpage
;---------------------------------------------------------------------
; o.s. dependant routines (MS-DOS)
;---------------------------------------------------------------------

;
; get pointer to end of free memory
; out:	[bx]	memtop pointer
;
getebf:	mov	ah,4ah				;keep 1 segment allocated
	mov	bx,1000h			;64k / 4 paragraphs
	int	21h
	mov	bx,10000h - stksiz
	ret

;
; open read file
; out:	c-flag	nc = ok, c = file not found (or no more handles)
;
opnseq:	mov	dx,offset fsp
	mov	ax,3d00h			;open for read only
	int	21h
	mov	[fhandle],ax
	ret

;
; close read file
;
closrd:	mov	bx,[fhandle]
	mov	ah,3eh				;close file handle
	int	21h
	ret

;
; get date/time stamp of opened file
;
; out:	cx	bit 0-4	  = seconds/2
;		bit 5-10  = minutes
;		bit 11-15 = hours
;	dx	bit 0-4   = day
;		bit 5-8   = month
;		bit 9-15  = year-1980
;
getdts:	mov	bx,[fhandle]
	mov	ax,5700h			;get date/time last change
	int	21h
	ret

%newpage
;
; read file buffer
; in :	si	offset address read buffer
; out:	c-flag	nc = ok, c = end-of-file of read error
;	si	past last character
;
; remark:	eof-condition is also set if the buffer
;		was partially read
;
rdfile:	mov	ah,3fh				;DOS read via file handle
	mov	bx,[fhandle]			;bx = file handle
	mov	cx,[buftop]			;cx = buffer size
	sub	cx,si
	mov	dx,si				;dx = start offset buffer
	int	21h				;do read
	jc	rdfil1				;on error: return nc
	add	si,ax				;adjust si
	cmp	si,[buftop]			;reflect eof in c-flag
rdfil1:	ret

%subttl "texts and buffers"
%newpage
	dataseg

;---------------------------------------------------------------------
; command table for text display mode
;---------------------------------------------------------------------

cmdtbl  dw	cmdlen

	db	KeyDown
	dw	lindn

	db	KeyUp
	dw	linup

	db	KeyPgDn
	dw	pagdn

	db	KeyPgUp
	dw	pagup

	db	KeyEnd
	dw	gtoebf

	db	KeyHome
	dw	gtobbf

	db	KeyRgt
	dw	posrig

	db	KeyLft
	dw	poslef

	db	cr
	dw	paglef

	db	'+'
	dw	nxtbuf

	db	'-'
	dw	gtobfl

	db	'C'
	dw	togctr

	db	'T'
	dw	togtab
	db	KeyDel
	dw	togtab

	db	'N'
	dw	tognum
	db	KeyIns
	dw	tognum

	db	'W'
	dw	togwst

	db	'L'
	dw	gtolin

	db	'F'
	dw	find

	db	'S'
	dw	findu

	db	'X'
	dw	findx

	db	'H'
	dw	toghex

	db	'?'
	dw	hlpcmd
	db	'/'
	dw	hlpcmd
	db	KeyF01
	dw	hlpcmd

	db	escape
	dw	exit
cmdlen	=	(this byte - (cmdtbl+1))/3

%newpage	
;---------------------------------------------------------------------
; command table for hexadecimal display mode
;---------------------------------------------------------------------

cmdtbx  dw	cmdlnx

	db	KeyDown
	dw	lindn

	db	KeyUp
	dw	linup

	db	KeyPgDn
	dw	pagdx

	db	KeyPgUp
	dw	pagup

	db	KeyEnd
	dw	gtoebf

	db	KeyHome
	dw	gtobbf

	db	'+'
	dw	nxtbuf

	db	'-'
	dw	gtobfl

	db	'H'
	dw	toghex

	db	'?'
	dw	hlpcmd
	db	'/'
	dw	hlpcmd
	db	KeyF01
	dw	hlpcmd

	db	escape
	dw	exit
cmdlnx	=	(this byte - (cmdtbx+1))/3
%newpage	
;---------------------------------------------------------------------
; help text for text display mode
;---------------------------------------------------------------------

txhelp	db lf
	db "COMMANDS TEXT DISPLAY MODE:",cr
	db lf
	db 'Down     line down              Up       line up',cr
	db 'PgDn     page down              PgUp     page up',cr
	db 'End      end of buffer          Home     start of buffer',cr
	db '+        next buffer            -        start of file',cr
	db 'Right    scroll right           Left     scroll left',cr
	db 'Enter    scroll max left        H        hex display',cr
	db 'F        find literal text      S        find text,ignore case',cr
	db 'X        find again             L        go to line number',cr
	db 'Del or T tab expansion          Ins or N line numbers',cr
	db 'C        control characters     W        Wordstar document',cr

	db '? or F1  help                   ESC      exit program',cr
	db lf
	db 'INFORMATION:',cr
	db lf
	db 'C        control on             c        control off',cr
	db 'T        tab expansion on       t        tab expansion off',cr
	db 'W        Wordstar on            w        Wordstar off',cr
	db '[        start of file          <        start of buffer',cr
	db ']        end of file            >        end of buffer',0

%newpage
;---------------------------------------------------------------------
; help text fod hexadecimal display mode
;---------------------------------------------------------------------

txhlpx	db lf
	db "COMMANDS HEXADECIMAL DISPLAY MODE:",cr
	db lf
	db 'Down     line down              Up       line up',cr
	db 'PgDn     page down              PgUp     page up',cr
	db 'End      end of buffer          Home     start of buffer',cr
	db '+        next buffer            -        start of file',cr
	db 'H        hex display off        ? or F1  help',cr
	db 'ESC      exit program',cr
	db lf
	db 'INFORMATION:',cr
	db lf
	db '[        start of file          <        start of buffer',cr
	db ']        end of file            >        end of buffer',0

%newpage
;---------------------------------------------------------------------
; other texts
;---------------------------------------------------------------------

txid	=	this byte
	db	cr,'SEE v1.1',cr
	db	'usage : SEE [dn:]filename.ext',cr
	db	0

txwild	db	'? and * are not allowed'
	db	0

txfile	db	'File ',0
txfnf	db	'not found',0
txleeg	db	'is empty',0

txhex	db	'HEX'
lnhex	=	this byte - txhex

txpstp	db	'ESC=stop'
lnpstp	=	this byte - txpstp

txphlp	db	'?=help'
lnphlp	=	this byte - txphlp

txnxbf	db	'Next buffer',0
txbfl	db	'Begin file',0
txline	db	'Line:',0
txtxt	db	'Find:',white,0
txtxth	db	'FIND:',white,0
txlnum	db	5 dup (?)
	db	': ',0
txtts	db 'Press any key to exit help',0

%newpage
;---------------------------------------------------------------------
; buffers, counters, etc.
;---------------------------------------------------------------------

bbfofs	dd ?			;file offset start of buffer
fhandle	dw ?			;input file handle
beglin	dw ?			;number of first line in current buffer
curlin	dw ?			;current line number
endlin	dw ?			;number of last line in current buffer
endtxt	dw ?			;eind afdrukbuffer
ovflen	dw ?			;length of overflow after endtxt
buftop	dw ?			;start of remaining free memory

cmdsta	db ?			;command status
bufsta	db ?			;buffer status
lefmar	db ?			;left margin
rigmar	db ?			;right margin
maxrig	db ?			;max right margin
chrcnt	db ?			;character count (text display)
hexcnt	dw ?			;character count (hexadecimale display)
inpcnt	db ?			;length of find text

hexbuf	db 16 dup (?)		;hexadecimal display line buffer
decbuf	db 5 dup (?)		;decimal number conversion buffer
txprm	db prmlen+1 dup (?)	;prompt text
inpbuf	db inplen+1 dup (?)	;input buffer find text
numbuf	db numlen+1 dup (?)	;input buffer line number

label	txtbuf	byte		;text buffer (remainder of free memory)

	end	see
