;-----------------------------------------------------------------------------
; name		: TECMDS.ASM
; object	: Tiny Editor - edit commands
; type		: include file
; version	: 1.7
; date		: Feb 20, 2000
; author	: J R Ferguson
;-----------------------------------------------------------------------------

;
;display command summary
;
help:		setsta	drwwin+drwsta+drwinf
		mov	si,offset xhelp			;display help
		xor	dh,dh				;at row 0
		call	putstr
		call	setcur				;set cursor
		mov	ah,0				;wait for keypress
		int	16h
		and	ah,ah				;special key:
		jz	helpfmtX			; return
		call	toupper				;with/without Ctrl-key
		jumpif	al,b,<'@'>,help1
		jumpif	al,a,<'_'>,help1
		sub	al,'@'
help1:		jumpif	al,ne,<'O'-ctrl>,helpfmtX
;;		jmp	helpfmt


;
;Display text fomatting status screen
;
helpfmt:	mov	si,offset xhelpfmt		;display help
		xor	dh,dh				;at row 0
		call	putstr
		call	setcur				;set cursor
		mov	ah,0				;wait for keypress
		int	16h
helpfmtX:	ret

		page
;
;change control character display mode (= display length)
;
;rotate backward through:
; 0 = no display
; 1 = literal display
; 2 = ^A, ^B, ... (Wordstar style)
;
chgctrmode:	setsta	updcol+drwwin+drwsta
		mov	al,[ctrmode]
		dec	al
		jns	chgctrmode1
		mov	al,2
		mov	si,offset xctrwst
		mov	bx,offset xstactrwst
		jmp	short chgctrmode2
chgctrmode1:	mov	si,offset xOff
		mov	bx,offset xstactroff
		and	al,al
		jz	chgctrmode2
		mov	si,offset xctrlit
		mov	bx,offset xstactrlit
chgctrmode2:	mov	[ctrmode],al
		mov	[msgptr],bx
		mov	di,offset ocd
		jmp	cpystr

		page
;
;copy left + right margin from current line
;
setLRmar:	mov	si,[pnt.curtxt]
		call	_getsol				;to start of line
		xor	cx,cx				;col = 0

setLRmar1:	call	_right				;search first nonblank
		jc	setLRmarX			;eol: no operation
		ifwhite	al,setLRmar1
		mov	ax,cx				;set left margin
		dec	ax
		xpush	<si,cx>
		call	setlftmar1
		xpop	<cx,si>

setLRmar2:	mov	bx,cx				;search last nonblank
setLRmar3:	call	_right
		jc	setLRmar4
		ifwhite	al,setLRmar3
		jmp	short setLRmar2
setLRmar4:	mov	ax,bx				;set right margin
		dec	ax
		call	setrgtmar1
		mov	si,offset xstalrmar
		mov	[msgptr],si
		setsta	drwsta
setLRmarX:	ret


;
;set left margin
;
setlftmar:	mov	ax,[lftmar]
		mov	si,offset xlftmar
		call	askmar
		jc	askmarX
setlftmar1:	mov	[lftmar],ax
		mov	di,offset oml
		jmp	short setrgtmar2


;
;set right margin
;
setrgtmar:	mov	ax,[rgtmar]
		mov	si,offset xrgtmar
		call	askmar
		jc	askmarX
setrgtmar1:	mov	[rgtmar],ax
		mov	di,offset omr
setrgtmar2:	inc	ax
		mov	cl,maxmar
		jmp	utoa


;
;ask margin, return [curtxtcol] if escaped
;
;in:	ax	current margin
;	ds:si	prompt string address
;out:	carry	NC = ok, C = aborted
;	ax	new margin
;
askmar:		inc	ax
		mov	bp,si
		mov	di,offset marstr
		mov	cl,maxmar
		call	utos
askmar1:	mov	si,bp
		asksi	marstr,maxmar
		jnc	askmar2
		jumpif	al,ne,escape,askmar4
		mov	ax,[curtxtcol]
		jmp	short askmar3
askmar2:	mov	si,offset marstr
		call	atou
		jc	askmar1
		and	ax,ax
		jz	askmar3
		dec	ax
askmar3:	clc
		ret

askmar4:	stc
askmarX:	ret

		page
;
;Various toggle routines
;
tglwrap:	toggle	wrapsw,xstawrapoff,xstawrapon,oww	;word wrap
tgljust:	toggle	justsw,xstajustoff,xstajuston,ojs	;justification
tgltrim:	toggle	trimsw,xstatrimoff,xstatrimon,ost	;trim mode
tglindent:	tglparm	indtsw,xstaindtoff,xstaindton,oai	;auto-indent
;;		jmp	short dotoggle


;
;Toggle a text formatting On/Off byte switch
;
;in:	bx	offset switch
;	ax	offset status message for Off condition
;	dx	offset status message for On  condition
;	di	offset On/Off text in text format help screen
;
;All offsets relative to ds register
;
dotoggle:	setsta	drwsta
		mov	si,offset xOff
		xor	byte ptr [bx],true
		jz	dotoggle1
		mov	si,offset xOn
		mov	ax,dx
dotoggle1:	mov	[msgptr],ax
		jmp	cpystr

		page
;
;reformat paragraph between left and right margin
;start at current position, stop at first empty line
;
reformat:	mov	word ptr [pnt.wrptxtend],nil
		call	putwait
		setsta	updrow+drwwin+drwsta
		mov	byte ptr [txtchgsw],true
		call	setprv
		mov	si,[pnt.curtxt]

reformat0:	mov	[pnt.wrpsepbeg],si
		call	skipsep				;skip separators
		mov	[pnt.wrpwrdbeg],si
		mov	bx,1
		jnc	reformat1
		jmp	reformatEnd2			; empty line: stop
reformat1:	mov	bx,0				;start without cr-lf

		mov	ax,[curtxtcol]			;if curtxtcol < lftmar
		mov	dx,[lftmar]
		jumpif	ax,nb,dx,reformat2
		mov	[wrpcol],dx			; col = lftmar
		sub	dx,ax				; fill to lftmar
		jmp	short reformat3			;else
reformat2:	mov	[wrpcol],ax			; col = curtxtcol
		mov	dx,0				; no fill
reformat3:	call	parsewrd			;always copy 1st word
		add	[wrpcol],cx
		mov	[pnt.wrpwrdend],si
		mov	[pnt.wrpjstbeg],si		;begin justification
		mov	word ptr [wrpsepcnt],0		;reset sep count

reformat4:	call	replsep				;replace previous sep
		jc	reformatX			;out of memory: stop
		mov	si,[pnt.wrpwrdend]
		mov	[pnt.wrpsepbeg],si
		call	parsesep			;skip sep
		mov	[pnt.wrpwrdbeg],si
		jc	reformatEnd			; end of para/end wrap
		call	parsewrd			;skip word
		mov	[pnt.wrpwrdend],si
		mov	ax,[wrpcol]			;test right margin
		add	ax,cx
		jumpif	ax,a,[rgtmar],reformat5		;if the word fits
		inc	ax				; adjust column
		mov	[wrpcol],ax
		inc	word ptr [wrpsepcnt]		; increment space count
		mov	bx,0				; insert 1 space
		mov	dx,1
		jmp	short reformat4			; loop next word

reformat5:	iffalse	<byte ptr [justsw]>,reformat6	;else if justify mode
		call	justify				;  justify spacing
		jc	replsepX
reformat6:	mov	bx,1				; insert cr-lf
		mov	dx,[lftmar]			; + left margin
		add	cx,dx				; adjust column
		mov	[wrpcol],cx
		mov	si,[pnt.wrpwrdend]		; set just beg ptr
		mov	[pnt.wrpjstbeg],si
		mov	word ptr [wrpsepcnt],0		; reset sep count
		jmp	short reformat4			; loop next word
reformatX:	ret

		;End of paragraph or end of wrap text
reformatEnd:	jumpif	si,b,[pnt.wrptxtend],reformatEnd1;if end wrap text
		xor	bx,bx				; no cr-lf
		mov	dx,1				; just 1 space
		jmp	short replsep			;else (end paragraph)
reformatEnd1:	mov	bx,2				; insert 2 cr-lf pairs
reformatEnd2:	xor	dx,dx				; no left margin
;;		jmp	short replsep

		page
;
;replace separator group by BX cr-lf pairs + DX spaces
;
;       Text pointers:			Others:
;
;in:	|old-separator|word|		BX = nr of cr-lf pairs in new sep
;	 ^             ^    ^		DX = nr of spaces in new separator
;	 |	       |    |
;	[pnt.wrpsepbeg]|   [pnt.wrpwrdend]
;		       |
;		      [pnt.wrpwrdbeg]
;
;out:	|new-separator|word|		carry:	NC = ok, C = out of memory
;	 ^	       ^    ^
;	 |	       |    |
;	[pnt.wrpsepbeg]|   [pnt.wrpwrdend]
;		       |
;		      [pnt.wrpwrdbeg]
;	              [pnt.curtxt]

replsep:	add	dx,bx				;make space
		add	dx,bx
		mov	di,[pnt.wrpsepbeg]
		mov	[pnt.curtxt],di
		mov	cx,[pnt.wrpwrdbeg]
		sub	cx,di
		sub	cx,dx
		jnb	replsep1
		neg	cx
		call	moveup
		jc	replsepX

replsep1:	mov	cx,bx				;insert cr-lf pairs
		mov	ax,crlf
		rep	stosw
		sub	dx,bx
		sub	dx,bx

		mov	cx,dx				;insert spaces
		mov	al,' '
		rep	stosb
		mov	[pnt.curtxt],di

		mov	dx,[pnt.wrpwrdbeg]		;delete unused space
		sub	dx,di
		jz	replsep2
		call	movedn
replsep2:	clc
replsepX:	ret

		page
;
;parse word for word wrap
;
;in,out:	si	text ptr
;out:		cx	word display width
;
parsewrd:	xor	cx,cx
parsewrd1:	jumpif	si,nb,[pnt.wrptxtend],skipsepX	;end wrp: stop
		jumpif	si,nb,[pnt.endtxt],skipsepX	;eof	: stop
		mov	al,es:[si]
		ifnsep	al,parsewrd2
		je	skipsepX			;space	: stop
		iftab	al,skipsepX			;tab	: stop
		call	_iseol				;eol	: stop
		jnc	skipsepX
		jmp	short parsewrd3			;control: skip col cnt
parsewrd2:	inc	cx				;increment col count
parsewrd3:	inc	si				;increment text ptr
		jmp	short parsewrd1			;loop next char


;
;parse separators for word wrap
;
;in,out:	si	text ptr
;out:		carry	C = end of paragraph or end of wrap text
;
parsesep:	call	skipsep				;skip separators
		jnc	skipsepX			;if end-line/end-wrap
;;		jmp	skipsep				; skip separators


;
;skip white space from source
;
;in,out:	es:si	text ptr
;out:		carry	C = end of line or end of wrap text
;
skipsep:	jumpif	si,nb,[pnt.wrptxtend],skipsep2
		call	_ateol
		jnc	skipsep1
		ifnsep	<byte ptr es:[si]>,skipsepX
		inc	si
		jmp	short skipsep
skipsep1:	call	_skfnwl
skipsep2:	stc
skipsepX:	ret

		page
;
;justify separator spacing (word wrap)
;
;out:	carry	NC = ok, C = out of memory
;
justify:	ifzero	<word ptr [wrpsepcnt]>,justifyX
		mov	ax,[rgtmar]
		inc	ax
		sub	ax,[wrpcol]
		jbe	justifyX
		push	cx
		mov	cx,[pnt.wrpsepbeg]
		sub	cx,[pnt.wrpjstbeg]
		jbe	justifyRet
		xor	dx,dx
		div	word ptr [wrpsepcnt]		;DX = remainder
		mov	bx,ax				;BX = quotient
		xor	[justupsw],true			;toggle direction
		jz	justdn

justup:		mov	di,[pnt.wrpjstbeg]		;-- Left to right --
		mov	al,' '
justup1:	repne	scasb				;find separator
		jne	justifyRet			; done (no more sep)
		mov	bp,cx
		mov	cx,bx				; space cnt = quotient
		and	dx,dx				; if remainder > 0
		jz	justup2
		inc	cx				;  inc space cnt
		dec	dx				;  dec remainder
justup2:	jcxz	justifyRet			;   done (no more fill)
		mov	[pnt.curtxt],di			;  insert spaces
		call	moveup
		jc	justifyErr
		rep	stosb
		mov	cx,bp
		jmp	short justup1			;loop next separator

justdn:		mov	di,[pnt.wrpsepbeg]		;-- Right to left --
		dec	di
		std
		mov	al,' '
justdn1:	repne	scasb				;find separator
		jne	justifyRet			; done (no more sep)
		mov	bp,cx
		mov	cx,bx				; space cnt = quotient
		and	dx,dx				; if remainder > 0
		jz	justdn2
		inc	cx				;  inc space cnt
		dec	dx				;  dec remainder
justdn2:	jcxz	justifyRet			;   done (no more fill)
		inc	di
		mov	[pnt.curtxt],di			;  insert spaces
		cld
		call	moveup
		jc	justifyErr
		std
		add	di,cx
		rep	stosb
		dec	di
		mov	cx,bp
		jmp	short justdn1			;loop next separator

justifyErr:	stc
		jmp	short justifyRet1
justifyRet:	clc
justifyRet1:	cld
		pop	cx
justifyX:	ret

		page
;
;move to top of screen
;
topscr:		mov	ax,[wintxtrow]
		jumpif	ax,e,[curtxtrow],topX
		mov	[curtxtrow],ax
		setsta	updptr+drwsta
		jmp	setprv


;
;move to top of file
;
top:		ifzero	<word ptr [pnt.curtxt]>,topX
		setsta	drwwin+drwsta
		call	setprv
		staxz	<pnt.curtxt,curtxtrow,curtxtcol,virtxtcol,curdspcol>
		stax	<pnt.winref,wintxtrow,windspcol>
topX:		ret


;
;move to bottom of screen
;
botscr:		mov	cx,[wintxtrow]
		add	cx,[maxwinrow]
		jumpif	cx,e,[curtxtrow],topX
		mov	[curtxtrow],cx
		setsta	updptr+drwsta
		jmp	setprv


;
;move to end-of-file
;
bottom:		mov	si,[pnt.endtxt]
		jumpif	si,e,[pnt.curtxt],bottomX
		call	setprv
		mov	[pnt.curtxt],si
		setsta	updrow+drwwin+drwsta
bottomX:	ret

		page
;
;set "previous" text marker
;
setprv:		iftrue	<byte ptr [prvmrksw]>,setprvX	;only once per command
		mov	ax,[pnt.curtxt]
		mov	[pnt.prvtxt],ax
		mov	byte ptr [prvmrksw],true
		mov	word ptr [chrdelcnt],0		;clear undo buffer
setprvX:	ret


;
;set numbered text marker
;
;in:	al	ASCII marker number
;
setmark:	mov	bl,al
		and	bx,000Fh
		add	bx,bx
		mov	si,[pnt.curtxt]
		mov	[pnt.usrtxt+bx],si
		ret


;
;various "go to marker" commands
;
tomark		macro	marker
		mov	si,word ptr [pnt.&marker&]
		jmp	short gtomark1
		endm

gtofind:	tomark	fndtxt	;position previous to last find command
gtoprev:	tomark	prvtxt	;previous position
tobegblk:	tomark	begblk	;block begin
toendblk:	tomark	endblk	;block end


;
;go to numbered text marker
;
;in:	al	ASCII marker number
;
gtomark:	mov	bl,al
		and	bx,000Fh
		add	bx,bx
		mov	si,[pnt.usrtxt+bx]
gtomark1:	jumpif	si,e,nil,gtomarkX		;exit if not defined
		jumpif	si,e,[pnt.curtxt],gtomarkX	;exit if positioned
		call	setprv
		mov	[pnt.curtxt],si
		setsta	updrow+drwwin+drwsta
gtomarkX:	ret

		page
;
;incrementing adjust of text pointers
;
;in:		si	lower bound for adjust range
;		cx	value to add
;changed:	flags
;
incpnt:		push	bx
		mov	bx,2*(pntcnt-1)
incpnt1:	jumpif	<word ptr [pnt+bx]>,e,nil,incpnt2;if defined
		jumpif	<word ptr [pnt+bx]>,b,si,incpnt2;and in adjust range
		add	word ptr [pnt+bx],cx		; add offset
incpnt2:	sub	bx,2				;loop
		jns	incpnt1
		pop	bx
incpntX:	ret


;
;to specified line number
;
gtolin:		ask	xlnr,lnrstr,maxlnr		;ask line number
		jc	incpntX				;escape: return
		jz	incpntX				;empty : return
		mov	si,offset lnrstr
		call	atou				;make numeric
		jc	gtolin				;error: ask again

		and	ax,ax
		jz	gtolin1
		dec	ax
gtolin1:	mov	[curtxtrow],ax
		staxz	<curtxtcol,virtxtcol,curdspcol>
		setsta	updptr+drwwin+drwsta
		jmp	setprv

		page
;
;repeat last find[/replace]
;
rfind:		ifzero	<byte ptr [findstr]>,incpntX
		call	setprv
		mov	si,[pnt.curtxt]			;save current position
		mov	[fndorgptr],si
		jmp	short find3a			;find[/replace]


;
;find/replace text
;
fndrep:		mov	byte ptr [fndrepsw],true	;replace
		jmp	short find1


;
;find text
;
find:		mov	byte ptr [fndrepsw],false	;no replace
;<fndrep entry>
find1:		ask	xfind,findstr,maxfind		;ask find string
		jc	find1Esc			;escape: exit
		jz	find1Esc			;empty : exit

		iffalse	<byte ptr [fndrepsw]>,find2	;if find/replace
		ask	xrepl,replstr,maxfind		; ask replace string
		jnc	find1a
		mov	byte ptr [fndrepsw],false
find1Esc:	jmp	findEsc				; esc exit (empty ok)
find1a:		mov	byte ptr [fndrepsw],true

find2:		ask	xfindopt,foptstr,maxfopt	;ask options
		jc	find1Esc
		call	foptparse
		jc	find2

find3:		call	setprv
		mov	si,[pnt.curtxt]			;save current position
		mov	[fndorgptr],si

		test	byte ptr [fopt],foptgen
		jz	find3a
		mov	word ptr [pnt.curtxt],0


;<rfind entry>
find3a:		mov	cx,[foptcnt]			;initialize count
		mov	[findcnt],cx
		mov	byte ptr [findsw],false		;reset find switch

find4:		mov	cx,[pnt.endtxt]
		sub	cx,[pnt.curtxt]
		jcxz	findNo
		push	cx
		call	putwait
		pop	cx
		mov	di,[pnt.curtxt]

		page
;Find[,replace] loop
find5:		call	testesc				;test keyboard break
		jc	findEsc
		call	matchfirst
		jc	findNo
		call	matchtail
		jnc	findYes
		jcxz	findNo
		jmp	short find5

findNo:		iftrue	<byte ptr [findsw]>,findEsc
		mov	[msgptr],offset xstanfd
findEsc:	setsta	drwsta
		ret

findYes:	mov	byte ptr [findsw],true		;indicate success
		dec	di
		mov	[fndbegptr],di
		mov	word ptr [chrdelcnt],0
		mov	si,[fndorgptr]			;get original position
		mov	[pnt.fndtxt],si			;set pre-find marker
		iffalse	<byte ptr [fndrepsw]>,findY2	;if find/replace mode
		mov	si,[fndbegptr]			; set current pointer
		mov	[pnt.curtxt],si
		setsta	updrow+drwwin+drwsta		; display row,col
		call	adjust
		test	byte ptr [fopt],foptnoq		; if interactive
		jnz	findY1
		setsta	updrow+drwwin			;  display text
		call	adjust
		mov	si,offset xrepl			;  ask replace Y/N
		call	prompt
		mov	si,offset replstr
		call	noyesat
		jc	findY1b				;  no : skip replace
		call	putwait				;  yes: wait

findY1:		setsta	drwwin				; replace string
		mov	byte ptr [txtchgsw],true
		mov	si,[fndendptr]
		call	delrng
		mov	si,offset replstr
		call	insstr
		jnc	findY1c				; out of memory:
		mov	si,offset findstr		;  undo change & exit
		call	insstr
		jmp	short findY4

findY1b:	mov	di,[fndendptr]			; no replace:
		mov	[pnt.curtxt],di			;  to end of match
		jumpif	al,ne,escape,findY1c
		jmp	findEsc

findY1c:	test	byte ptr [fopt],foptgen		;general?
		jnz	findY3
findY2:		dec	byte ptr [findcnt]		;n times?
		jz	findY4
findY3:		mov	di,[pnt.curtxt]			;loop find[,replace]
		mov	cx,[pnt.endtxt]
		sub	cx,di
		jbe	findY4
		mov	[fndorgptr],di
		jmp	find5
;End find[,replace] loop

findY4:		setsta	updrow+drwwin+drwsta+drwinf	;adjust screen
		ret

		page
;
;match first char
;
matchfirst:	mov	si,offset findstr
		lodsb
		test	byte ptr [fopt],foptupp
		jnz	matchf1

		repne	scasb				;literal case compare
		jne	matchfXC
		jmp	short matchfXNC

matchf1:	call	toupper				;uppercase compare
		mov	ah,al
matchf2:	jcxz	matchfXC
		mov	al,es:[di]
		inc	di
		dec	cx
		call	toupper
		caseal	ah,matchfXNC
		jmp	short matchf2

matchfXNC:	clc
		ret
matchfXC:	stc
		ret


;
;match tail
;
matchtail:	xpush	<cx,di>
		test	byte ptr [fopt],foptupp
		jnz	matcht2

matcht1:	lodsb					;literal compare
		and	al,al
		je	matchtYes
		jcxz	matchtNo
		dec	cx
		scasb
		je	matcht1
		jmp	short matchtNo

matcht2:	lodsb					;upper case compare
		and	al,al
		je	matchtYes
		jcxz	matchtNo
		call	toupper
		mov	ah,al
		dec	cx
		mov	al,es:[di]
		inc	di
		call	toupper
		caseal	ah,matcht2
		jmp	short matchtNo

matchtYes:	mov	[fndendptr],di
		mov	[pnt.curtxt],di
		clc
		jmp	short matchtR

matchtNo:	stc
matchtR:	xpop	<di,cx>
		ret

		page
;
;parse find/replace options
;
;out:	carry	NC = ok, C = unknown option
;
 setfopt	macro	char,mask
		mov	ah,&mask&
		caseal	<&char&>,foptparse2
		endm
;
foptparse:	mov	si,offset foptstr
		mov	byte ptr [fopt],00h
		mov	word ptr [foptcnt],1

foptparse1:	mov	al,[si]
		and	al,al
		jz	foptparseX
		call	toupper

		setfopt	<'G'>,foptgen
		setfopt	<'U'>,foptupp
		setfopt	<'N'>,foptnoq
;		setfopt	<'B'>,foptbck
;		setfopt	<'W'>,foptwrd

		jumpif	al,b,<'0'>,foptparseErr
		jumpif	al,a,<'9'>,foptparseErr
		call	atou
		and	ax,ax
		jz	foptparseErr
		mov	[foptcnt],ax
		jmp	short foptparse1

foptparse2:	or	[fopt],ah
		inc	si
		jmp	short foptparse1

foptparseErr:	beep					;error
		stc
foptparseX:	ret


		page
;
;delete to start of line
;
delsol:		ifzero	[curtxtcol],foptparseX
		setsta	drwrow+drwsta
		staxz	<curtxtcol,virtxtcol,curdspcol>
		mov	si,[pnt.curtxt]
		mov	di,si
		call	_getsol
		jmp	short deleol1


;
;delete to end-of-line
;
deleol:		mov	si,[pnt.curtxt]
		mov	di,si
		call	_geteol
		jumpif	si,e,di,foptparseX
		xchg	si,di
deleol1:	mov	byte ptr [dellinsw],false
		setsta	drwrow
		jmp	short dellin1


;
;delete current line
;
dellin:		setsta	drwdwn+drwsta
		staxz	<curtxtcol,virtxtcol,curdspcol>
		mov	byte ptr [dellinsw],true
		mov	si,[pnt.curtxt]
		call	_getsol
		mov	di,si
		call	_nxtsol
		xchg	si,di
;;		jmp	short dellin1


;
;delete (partial) line
;
;in :	si		start offset of text to delete
;	di		end offset of text to delete
;	[dellinsw]	delete full line (true/false)
;
dellin1:	mov	cx,di				;compute byte count
		sub	cx,si
		jz	deleteX				;return if 0

		mov	byte ptr [txtchgsw],true
		jumpif	cx,be,maxlindel,dellin2		;avoid buffer overflow
		mov	cx,maxlindel
dellin2:	mov	[lindelcnt],cx
		mov	[pnt.curtxt],si
		mov	es,[progseg]
		mov	di,offset lindelbuf
;;		jmp	short delete

		page
;
;delete text
;
;in:		si	start address of delete range
;		cx	number of bytes to delete
;		es:di	start address of undelete save buffer
;out:		es	cs:[textseg]
;
delete:		jcxz	deleteR
		mov	[delptr],si			;tmp save text ptr
		mov	[delcnt],cx			;tmp save byte count
		mov	ds,[textseg]
		rep	movsb				;store to undel buffer

		mov	es,cs:[textseg]			;delete text
		mov	di,cs:[delptr]
		mov	si,di
		add	si,cs:[delcnt]
		mov	cx,cs:[pnt.endtxt]
		sub	cx,si
		rep	movsb

		mov	ds,cs:[progseg]
		mov	si,[delptr]			;adjust text pointers
		mov	cx,[delcnt]
		jmp	decpnt

deleteR:	mov	es,cs:[textseg]
deleteX:	ret


;
;delete word right
;
delwrd:		setsta	drwdwn
		xpush	<<word ptr [chrdelcnt]>,<word ptr [pnt.curtxt]>>
		call	rgtwrd
		mov	si,[pnt.curtxt]
		xpop	<<word ptr [pnt.curtxt]>,<word ptr [chrdelcnt]>>
		mov	byte ptr [txtchgsw],true
;;		jmp	short delrng

		page
;
;delete range of characters starting at [pnt.curtxt]
;save in character undelete buffer
;
;in :	si	pointer to end of range
;
delrng:		mov	cx,si				;cx = byte count
		mov	si,[pnt.curtxt]			;si = txt ptr
		sub	cx,si
		jbe	deleteX

		mov	dx,cx				;dx = byte count
		mov	bx,[chrdelcnt]			;bx = chrdelcnt
		mov	ax,maxchrdel			;cx = undo count
		sub	ax,bx
		jumpif	cx,b,ax,delrng1
		mov	cx,ax
delrng1:	jcxz	delrng5				;store to undo buffer
		iffalse	<byte ptr [dellftsw]>,delrng3	;if delete left
		and	bx,bx				; if chrdelcnt > 0
		je	delrng2
		mov	ax,cx				;  ax = undo count
		mov	bp,si				;  bp = txt ptr
		mov	si,offset chrdelbuf - 1		;  move up
		add	si,bx
		mov	di,si
		add	di,cx
		mov	cx,bx
		std
		mov	es,[progseg]
		rep	movsb
		mov	es,[textseg]
		cld
		mov	si,bp				;  si = txt ptr
		mov	cx,ax				;  cx = undo count
delrng2:	mov	di,offset chrdelbuf		; store at start
		jmp	short delrng4

delrng3:	mov	di,offset chrdelbuf		;else
		add	di,bx				; store at end
delrng4:	add	[chrdelcnt],cx
		mov	ax,ds
		mov	bx,es
		mov	ds,bx
		mov	es,ax
		rep	movsb
		mov	ds,ax
		mov	es,bx
delrng5:	;;jmp	movedn				;delete from text

		page
;
;delete dx characters starting at [pnt.curtxt] and adjust markers
;
movedn:		and	dx,dx
		jz	decpntX
		mov	di,[pnt.curtxt]			;del chars
		mov	si,di
		add	si,dx
		mov	cx,[pnt.endtxt]
		sub	cx,si
		jcxz	movedn1
		mov	ds,[textseg]
		rep	movsb
		mov	ds,cs:[progseg]

movedn1:	mov	si,[pnt.curtxt]			;adjust pointers
		mov	cx,dx
;;		jmp	decpnt


;
;decrementing adjust of text pointers
;
;in:		si	lower bound for adjust range
;		cx	value to subtract
;changed:	flags
;
decpnt:		xpush	<ax,bx>
		mov	bx,2*(pntcnt-1)
decpnt1:	mov	ax,word ptr [pnt+bx]
		jumpif	ax,e,nil,decpnt4		;if undefined no change
		jumpif	ax,b,si,decpnt4			;if in adjust range
		sub	ax,cx				; subtract offset
		jc	decpnt2				; if overflow
		jumpif	ax,ae,si,decpnt3		; or in deleted range
decpnt2:	mov	ax,si				;  to start of range
decpnt3:	mov	word ptr [pnt+bx],ax		; store
decpnt4:	sub	bx,2
		jns	decpnt1				;loop
		xpop	<bx,ax>
decpntX:	ret

		page
;
;delete current character
;
delchr:		mov	si,[pnt.curtxt]			;if end-of-text
		jumpif	si,nb,[pnt.endtxt],delleftX	; return
		mov	byte ptr [txtchgsw],true
		call	_ateol				;if end-of-line
		jc	delchr1
		call	_skfnwl				; delete eol
		setsta	drwdwn				; redraw below
		jmp	delrng				;else
delchr1:	inc	si				; delete current char
		setsta	drwrow				; redraw line
delchr2:	jmp	delrng


;
;delete character left
;
delleft:	mov	si,[pnt.curtxt]			;if start-of-text
		and	si,si
		jz	delleftX			; return
		ifnzero	<word ptr [curtxtcol]>,delleft1	;if start-of-line
		push	si				; delete eol backward
		call	_skbnwl
		mov	[pnt.curtxt],si
		pop	si
		setsta	updrow+drwwin			; redraw window
		jmp	short delleft4			;else
delleft1:	iffalse	<byte ptr [indtsw]>,delleft3	; if auto-indent mode
		iftrue	<byte ptr [wrapsw]>,delleft3	; and no word wrap
		call	unindent			;  attempt to unindent
		jnc	delleftX			;  if success return
		mov	si,[pnt.curtxt]			;  else del char back
delleft3:	dec	word ptr [pnt.curtxt]		; else del char back
delleft4:	mov	byte ptr [dellftsw],true
		call	delrng
		mov	byte ptr [dellftsw],false
		setsta	updcol+drwrow+drwsta		; redraw line
		mov	byte ptr [txtchgsw],true
delleftX:	ret

		page
;
;Attempt to unindent to next smaller indent level of lines above.
;Report failure if
; a) there is at least one non-blank character left of the cursor, or
; b) there is no lower indent level at lines above the cursor.
;
;in:	si	current text pointer
;out:	flags	NC = success, C = failure
;
unindent:	call	_getsol				;to start of line
		mov	di,si				;save sol ptr cur line
		call	indlevel			;check indent level
		jc	unindentX			;too low: failure
unindent1:	and	si,si				;check start of text
		jz	unindentC
		call	_prvsol				;to prev sol
		call	indlevel			;check indent level
		jnc	unindent1			;same or above: loop

		push	cx				;save new margin
		mov	si,[pnt.curtxt]			;delete current margin
		mov	[pnt.curtxt],di
		mov	byte ptr [dellftsw],true
		call	delrng
		mov	byte ptr [dellftsw],false
		pop	cx				;restore margin
		call	fill				;insert spaces
		setsta	updcol+drwrow+drwsta		;redraw line
		mov	byte ptr [txtchgsw],true
		clc					;report success
		jmp	short unindentX
unindentC:	stc
unindentX:	ret


;
;check indent level from start of line
;skip spaces and tabs until other char is found or [curtxtcol] reached
;
;in:	si	text ptr to start of line
;out:	si	unchanged
;	cx	text col where stopped
;	flags	C = stopped below [curtxtcol]
;		NC= stopped at or above [curtxtcol]
;
indlevel:	mov	bx,si				;save sol ptr
		xor	cx,cx
indlevel1:	jumpif	cx,nb,[curtxtcol],indlevel2	;check cur col
		call	_right				;right char
		jc	indlevel2			;eol: return C
		ifwhite	al,indlevel1			;loop if space or tab

		dec	cx				;compute margin
		cmp	cx,[curtxtcol]			;compare cur col
indlevel2:	mov	si,bx				;restore sol ptr
		ret

		page
;
;character left
;
left:		mov	si,[pnt.curtxt]			;if start-of-text
		and	si,si
		jz	leftX				; return

		call	setprv
		ifnzero	<word ptr [curtxtcol]>,left1	;if start-of-line
		call	_skbnwl				; skip nwl backward
		mov	[pnt.curtxt],si
		setsta	updrow+drwsta
		ret

left1:		dec	word ptr [pnt.curtxt]		;else char left
		setsta	updcol+drwsta
leftX:		ret


;
;character right
;
right:		mov	si,[pnt.curtxt]			;if end-of-text
		jumpif	si,nb,[pnt.endtxt],rightX				; return

		call	setprv
		call	_ateol				;if end-of-line
		jc	right1
		call	_skfnwl				; skip nwl forward
		mov	[pnt.curtxt],si
		setsta	updrow+drwsta
		ret

right1:		inc	word ptr [pnt.curtxt]		;else char right
		setsta	updcol+drwsta
rightX:		ret

		page
;
;left word
;
lftwrd:		mov	si,[pnt.curtxt]			;if start-of-text
		mov	cx,si
		jcxz	lftwrdX				; exit

		setsta	updcol+drwsta
		call	setprv
lftwrd1:	dec	si				;repeat char left
		mov	al,es:[si]			;until word-char
		ifnsep	al,lftwrd4
		call	_iseol				;   or newline
		jnc	lftwrd2
		loop	lftwrd1				;   or start-of-text
		jmp	short lftwrdRet			;start-of-text: return

lftwrd2:	inc	si				;newline: to prv eol
		setsta	updrow
		call	_skbnwl
		jmp	short lftwrdRet

lftwrd3:	dec	si				;skip to start-of-word
		ifsep	<byte ptr es:[si]>,lftwrd5
lftwrd4:	loop	lftwrd3				;  or start-of-text
		jmp	short lftwrdRet

lftwrd5:	inc	si
lftwrdRet:	mov	[pnt.curtxt],si
lftwrdX:	ret


;
;right word
;
rgtwrd:		mov	si,[pnt.curtxt]			;if eof
		jumpif	si,nb,[pnt.endtxt],rgtwrdX	; exit

		call	setprv
		call	_ateol				;if eol
		jc	rgtwrd0
		call	_skfnwl				; to next line
		setsta	updrow+drwsta
		jmp	short rgtwrd1
rgtwrd0:	call	_nxtsep				;else to end of word
		setsta	updcol+drwsta

rgtwrd1:	jumpif	si,nb,[pnt.endtxt],rgtwrd3	;to next word,eol,eof
		mov	al,es:[si]
		inc	si
		call	_iseol
		jnc	rgtwrd2
		ifsep	al,rgtwrd1
rgtwrd2:	dec	si
rgtwrd3:	mov	[pnt.curtxt],si
rgtwrdX:	ret

		page
;
;window right
;
sright:		mov	si,[pnt.curtxt]
		call	_ateol
		jnc	rgtwrdX

		mov	cx,[curdspcol]
		sub	cx,2
		add	cx,[maxwincol]
		jmp	short sleft1


;
;window left
;
sleft:		mov	cx,[curtxtcol]
		and	cx,cx
		jz	rgtwrdX

		add	cx,2
		sub	cx,[maxwincol]
		jnc	sleft1
		xor	cx,cx
sleft1:		mov	[virtxtcol],cx
		setsta	updptr+drwsta
		jmp	setprv


;
;mark word at or left of cursor
;
mrkwrd:		mov	si,[pnt.curtxt]			;if in word separator
		ifnsep	<byte ptr es:[si]>,mrkwrd1
		call	lftwrd				; to start of prev word
mrkwrd1:	mov	si,[pnt.curtxt]
		call	_nxtsep				;to end of word
		mov	[pnt.curtxt],si
		call	blkend				;set marker
		call	lftwrd				;to start of word
		jmp	blkbeg				;set marker


;
;to start of current line
;
gtosol:		staxz	<curtxtcol,virtxtcol,curdspcol>
		ifzero	[windspcol],gtosol1
		mov	[windspcol],0
		setsta	drwwin
gtosol1:	setsta	updptr+drwsta
		jmp	setprv


;
;move cursor to end of current line
;
gtoeol:		call	putwait
		setsta	updcol+drwsta
		mov	si,[pnt.curtxt]
		mov	di,si
		call	_geteol
		jumpif	si,e,di,gtoeolX
		call	setprv
		mov	[pnt.curtxt],si
gtoeolX:	ret

		page
;
;cursor up
;
up:		ifzero	<word ptr [curtxtrow]>,upX	;if at top row exit
		dec	[curtxtrow]			;line up
		setsta	updptr+drwsta
		call	setprv
upX:		ret


;
;scroll line up
;
sup:		ifzero	<word ptr [wintxtrow]>,upX	;if at top window exit

		setsta	drwwin				;need redraw
 		mov	si,[pnt.winref]			;scroll window up
		call	_prvsol
		mov	[pnt.winref],si
		dec	word ptr [wintxtrow]

		mov	cx,[wintxtrow]			;if txtrow below window
		add	cx,[maxwinrow]
		jumpif	cx,ae,[curtxtrow],upX
		mov	[curtxtrow],cx			; line up
		setsta	updptr+drwsta
		jmp	setprv


;
;move cursor down one line
;
down:		mov	si,[pnt.curtxt]			;to next sol
		call	_nxtsol				;if last line
		jc	upX				; exit

		inc	word ptr [curtxtrow]
		setsta	updptr+drwsta
		jmp	setprv


;
;scroll line up
;
sdown:		mov	si,[pnt.winref]			;if in last page
		call	_nxtpag
		jc	upX				; exit

		setsta	drwwin				;need redraw
		mov	si,[pnt.winref]			;scroll window down
		call	_nxtsol
		mov	[pnt.winref],si
		inc	word ptr [wintxtrow]

		mov	cx,[wintxtrow]			;if top window row
		jumpif	cx,be,[curtxtrow],upX
		mov	[curtxtrow],cx			; line down
		setsta	updptr+drwsta
		jmp	setprv

		page
;
;page down
;
pgdn:		mov	si,[pnt.curtxt]			;page down
		call	_nxtpag				;but not beyond eof
		add	[curtxtrow],bx
		setsta	updptr+drwsta
		jmp	setprv


;
;page up
;
pgup:		mov	cx,[curtxtrow]			;if at first line
		and	cx,cx
		je	blktoggleX			; exit

		sub	cx,[maxwinrow]			;else page up
		jnc	pgup1
		xor	cx,cx				;but not before tof
pgup1:		mov	[curtxtrow],cx
		setsta	updptr+drwsta
		jmp	setprv


;
;toggle insert/overwite mode
;
tglins:		setsta	drwsta
		xor	byte ptr [isrtsw],true
		mov	si,offset xinsmode
		jnz	tglins1
		mov	si,offset xovrmode
tglins1:	mov	di,offset xstains
		jmp	cpystr

		page
;
;set block begin marker
;
blkbeg:		mov	si,[pnt.curtxt]
		mov	[pnt.begblk],si
		jmp	short blkshow


;
;set block end marker
;
blkend:		mov	si,[pnt.curtxt]
		mov	[pnt.endblk],si
;;		jmp	short blkshow


;
;hide/show block depending on validity
;
blkshow:	setsta	drwwin
		mov	byte ptr [blkshwsw],false
;;		jmp	short blktoggle


;
;toggle block show/hide state
;
blktoggle:	call	validblk			;get block parameters
		jc	blktoggleX			;return if not valid
		not	byte ptr [blkshwsw]		;toggle show state
		jumpif	di,b,[pnt.winref],blktoggleX	;exit if before window
		setsta	drwwin				;else may need redraw
blktoggleX:	ret

		page
;
;read block error entry
;
blkreadErr:	mov	si,offset xstanfd		;prepare status message
		jumpif	ax,e,errfnf,blkreadErr1
		mov	si,offset xstamem
		jumpif	ax,e,errmem,blkreadErr1
		mov	si,offset xstaread
blkreadErr1:	mov	[msgptr],si			;display status line
		call	putsta
;;		jmp	short blkread			;prompt again


;
;read block
;
blkread:	mov	si,offset xread			;prompt for filename
		call	getfspblk
		jc	blkreadX

		call	putwait
		mov	byte ptr [txtchgsw],true
		mov	si,offset fspblk		;read block
		call	dskread
		jnz	blkreadErr			;error: prompt again

		mov	si,[pnt.curtxt]			;set block pointers
		mov	[pnt.begblk],si
		add	si,cx
		mov	[pnt.endblk],si
		mov	byte ptr [blkshwsw],true	;set block show on
		setsta	drwwin
blkreadX:	ret


;
;write marked block
;
blkwrite:	call	activeblk			;check block parameters
		jc	blkwriteX			;invalid/hidden: return

blkwrite1:	mov	si,offset xwrite		;get filespec
		call	getfspblk
		jc	blkwriteX

		call	validblk			;get block parameters
		mov	dx,offset fspblk
		call	dskwriteif			;write block
		jc	blkwrite1			;on error: prompt again
blkwriteX:	ret


		page
;
;delete marked block
;
blkdel:		call	activeblk			;check block parameters
		jc	blkwriteX			;invalid/hidden: return

		call	putwait
		mov	byte ptr [txtchgsw],true
		call	validblk			;get block parameters
		mov	[blkdelcnt],cx			;save to blk undel buf
		mov	es,[cutseg]
		xor	di,di
		call	delete

		mov	byte ptr [blkshwsw],false	;undefine block
		mov	word ptr [pnt.begblk],nil
		mov	word ptr [pnt.endblk],nil
		setsta	updrow+drwwin+drwsta
		ret

		page
;
;get block parameters
;check if valid, not hidden, and not including current text pointer
;
;out:	carry	NC = ok, C = invalid, hidden or including current pointer
;		NZ = non-adjacent, Z = adjacent to current pointer
;	si	begin block pointer
;	di	end block pointer
;	cx	block size in bytes
;	dx	current text pointer
;
transportblk:	call	activeblk			;get block parms
		mov	dx,[pnt.curtxt]			;get current pointer
		jc	transportblkX			;check invalid/hidden
		jumpif	si,nb,dx,transportblkX		;check overlap
		cmp	dx,di
transportblkX:	ret


;
;get block parameters, check if valid and not hidden
;
;out:	carry	NC=ok, C=invalid or hidden
;	si	begin block pointer
;	di	end block pointer
;	cx	block size in bytes
;
activeblk:	call	validblk			;get parms
		jc	validblkX			;check if valid
		xor	al,al
		cmp	al,[blkshwsw]			;check if hidden
		jmp	short validblk1


;
;get block parameters, check if valid
;
;out:	carry	NC=ok, C=invalid
;	si	begin block pointer
;	di	end block pointer
;	cx	block size in bytes
;
validblk:	mov	si,[pnt.begblk]
		mov	di,[pnt.endblk]
		mov	cx,di
		sub	cx,si
		jumpif	si,e,nil,validblk1
		jumpif	di,e,nil,validblk1
		cmp	si,di
validblk1:	cmc
validblkX:	ret

		page
;
;mark current line
;
mrklin:		mov	si,[pnt.curtxt]
		call	_getsol
		mov	[pnt.begblk],si
		mov	[pnt.curtxt],si
		call	_nxtsol
		mov	[pnt.endblk],si
		mov	byte ptr [blkshwsw],true
		setsta	updcol+drwwin+drwsta
		ret


;
;copy marked block to current position
;
blkcopy:	call	transportblk			;check block parameters
		jc	blkcopyX			;return if not ok

		call	putwait
		mov	byte ptr [txtchgsw],true
		call	validblk			;get block parameters
		call	moveup				;make space
		jc	blkcopyX			;out of memory: return

		mov	si,[pnt.begblk]			;copy block
		mov	di,[pnt.curtxt]
		mov	[pnt.begblk],di
		mov	ds,[textseg]
		rep	movsb
		mov	ds,cs:[progseg]
		mov	[pnt.endblk],di
		setsta	drwwin+drwsta
blkcopyX:	ret


;
;move marked block to current position
;
blkmove:	call	transportblk			;check block parameters
		jbe	validblkX			;return if not ok   (C)
							;	or adjacent (Z)
		mov	byte ptr [txtchgsw],true
		call	blkdel				;move via blk undel buf
;;		jmp	blkundel

		page
;
;insert contents of block delete buffer at current position
;
blkundel:	mov	cx,[blkdelcnt]			;cx= char count
		jcxz	blkundelX			;return if 0

		call	putwait
		mov	byte ptr [txtchgsw],true
		mov	cx,[blkdelcnt]
		call	moveup				;make space
		jc	blkundelX			;out of memory: return

		xor	si,si				;restore block
		mov	di,[pnt.curtxt]
		mov	[pnt.begblk],di			;set begin block marker
		mov	ds,[cutseg]
		rep	movsb
		mov	ds,cs:[progseg]
		mov	[pnt.endblk],di			;set end block marker

		mov	byte ptr [blkshwsw],true	;show block
		setsta	drwwin
blkundelX:	ret


;
;print block
;
blkprint:	call	activeblk			;check block parameters
		jc	blkprintX			;invalid/hidden:return

		mov	ah,2				;get printer status
		xor	dx,dx				;lpt1:
		int	17h
		test	ah,80h				;printer busy?
		jz	blkprintX			;yes
		test	ah,20h				;printer ack?
		jnz	blkprintX			;no

		call	putwait
		call	validblk			;get block parameters
blkprint1:	call	testesc				;check abort command
		jc	blkprintX
		mov	al,es:[si]			;fetch char
		inc	si
		xor	ah,ah				;print char
		xor	dx,dx				;use LPT1:
		int	17h
		ror	ah,1				;time out?
		jb	blkprintX			;yes: quit
		loop	blkprint1			;next char

		mov	al,cr				;print cr
		xor	ah,ah
		xor	dx,dx				;use LPT1:
		int	17h
blkprintX:	ret

		page
;
;remove trailing blanks in current block
;
blktrim:	call	activeblk			;check block parameters
		jc	blktrimX			;invalid/hidden:return

		call	putwait
		mov	si,[pnt.curtxt]			;save current ptr
		mov	[pnt.tmpsave],si
		call	validblk			;get block parameters
blktrim1:	call	testesc				;check abort command
		jc	blktrim2
		call	_geteol				;to end of line
		jumpif	si,nb,di,blktrim2		;check end block mark
		mov	[pnt.curtxt],si
		push	di
		call	trim				;delete trailing blanks
		pop	di
		mov	si,[pnt.curtxt]
		call	_nxtsol				;next line
		jnc	blktrim1			;loop if not eof
blktrim2:	mov	si,[pnt.tmpsave]		;restore current ptr
		mov	[pnt.curtxt],si
blktrimX:	ret

		page
;
;move current line up
;
linup:		ifzero	<word ptr [curtxtrow]>,blktrimX

		mov	byte ptr [txtchgsw],true
		call	dellin
		ifzero	<word ptr [lindelcnt]>,blktrimX

		call	setprv
		dec	word ptr [curtxtrow]
		mov	byte ptr [status],updptr+drwsta+drwinf
		call	adjust
		jmp	short linundel


;
;move current line down
;
lindown:	mov	si,[pnt.curtxt]
		call	_nxtsol
		jc	blktrimX

		mov	byte ptr [txtchgsw],true
		call	dellin
		ifzero	<word ptr [lindelcnt]>,blktrimX

		call	setprv
		inc	word ptr [curtxtrow]
		mov	byte ptr [status],updptr+drwsta+drwinf
		call	adjust
		setsta	drwwin
		jmp	short linundel


;
;repeat current line
;
rptlin:		mov	byte ptr [txtchgsw],true
		call	dellin
		call	linundel
;;		jmp	short linundel

		page
;
;undelete line
;
linundel:	mov	byte ptr [txtchgsw],true
		iffalse	<byte ptr [dellinsw]>,linundel1
		call	gtosol
linundel1:	mov	cx,[lindelcnt]
		mov	si,offset lindelbuf
		jmp	short restore


;
;re-insert deleted/replaced characters
;
undo:		mov	byte ptr [txtchgsw],true
		xor	cx,cx
		xchg	cx,[chrdelcnt]
		mov	si,offset chrdelbuf
;;		jmp	short restore


;
;restore deleted characters
;in: cs:si=buffer, cx=count
;
restore:	call	moveup
		jc	restoreX
		mov	di,[pnt.curtxt]
		rep	movsb				;insert from del buf
		setsta	drwdwn
restoreX:	ret

		page
;
;file menu
;
filemenu:	mov	si,offset xfmnu
		call	prompt
		mov	ah,0
		int	16h
		call	toupper
		caseal	escape,restoreX
		caseal	<'U'-ctrl>,restoreX
		mov	si,offset fmnutbl
		call	docmd
		jnc	restoreX
		beep					;unknown key: beep
		jmp	short filemenu			; wait for next key


;
;load new file
;
loadnew:	mov	si,offset xload
		iffalse	<byte ptr [txtchgsw]>,loadnew0	;if text changed
		beep					; sound beep
		mov	si,offset xabandon		; add warning
loadnew0:	asksi	fspmain,maxfsp
		jc	loadnew2

		call	putwait
		call	load
		and	ax,ax
		mov	si,offset xstaidn
		jz	loadnew2
		mov	si,offset xstanfd
		dec	ax
		jz	loadnew1
		mov	si,offset xstamem
		dec	ax
		jz	loadnew1
		mov	si,offset xstaread
loadnew1:	mov	[msgptr],si
loadnew2:	setsta	drwwin+drwsta+drwinf
		ret


;
;discard current file, start new empty file
;
newfile:	iffalse	<byte ptr [txtchgsw]>,newfile1	;if text was changed
		beep					; sound beep
		mov	si,offset xdiscard		; ask permission
		call	noyes
		jc	newfile2
newfile1:	mov	byte ptr [fspmain],0
		call	load
newfile2:	setsta	drwwin+drwsta+drwinf
		ret

		page
;
;exit command: save changes and exit
;
exit:		mov	si,offset xexit			;exit prompt
		call	save1				;save changes
		jc	quitX				;resume if aborted
		jmp	short quit1


;
;quit editor
;
quit:		mov	si,offset xquit			;display prompt
		call	prompt
		iffalse	<byte ptr [txtchgsw]>,quit0	;if text was changed
		beep					; sound beep
		mov	si,offset xdot
		call	promptat
		mov	si,offset xdiscard		; display warning
		call	promptat
quit0:		call	noyesat				;ask permission
		jc	quitX
quit1:		mov	byte ptr [endprgsw],true
quitX:		ret

		page
;
;save changes
;
;out:	carry	cond C	= save aborted
;		cond NC	= save succeeded
;
save:		mov	si,offset xsave			;save prompt
save1:		asksimod fspmain,maxfsp			;get filespec
		jc	saveX				;escape: abort
		stc
		jz	saveX				;empty : abort

		call	putwait
		mov	si,offset fspmain
		call	upstr

		mov	si,offset exttmp		;prepare .$$$ fsp
		mov	di,offset fsptmp
		call	cpyfsp
		mov	si,offset extbak		;prepare .BAK fsp
		mov	di,offset fspbak
		call	cpyfsp

		mov	dx,offset fsptmp		;write .$$$
		mov	si,0
		mov	cx,[pnt.endtxt]
		call	dskwrite
		jc	saveX				;error: abort

		mov	es,[progseg]
		mov	dx,offset fspbak
		mov	ah,41h				;delete .BAK
		int	21h
		mov	di,offset fspbak
		mov	dx,offset fspmain
		mov	ah,56h				;rename org to .BAK
		int	21h
		mov	di,offset fspmain
		mov	dx,offset fsptmp
		mov	ah,56h				;rename .$$$ to org
		int	21h

		mov	al,' '				;update status line
		mov	cx,maxfsp
		mov	di,offset xstafsp
		rep	stosb
		mov	si,offset fspmain
		mov	di,offset xstafsp
		call	cpystr
		setsta	drwsta

		mov	es,[textseg]
		mov	byte ptr [txtchgsw],false
		clc					;report success
saveX:		ret

		page
;
;set cursor at current window position
;
setwincur:	mov	ax,[curtxtrow]
		sub	ax,[wintxtrow]
		mov	dh,al
		mov	ax,[curdspcol]
		sub	ax,[windspcol]
		mov	dl,al
;;		jmp	short setcur
;
;set cursor position to screen row dh, col dl
;
setcur:		mov	ah,02h				;set cursor position
		xor	bh,bh				;screen 0
		int	10h
		ret

;--- END TECMDS.ASM ----------------------------------------------------------
