;-----------------------------------------------------------------------------
; name		: TEMAIN.ASM
; object	: Tiny Editor - main program
; type		: include file
; version	: 1.7
; date		: Feb 20, 2000
; author	: J R Ferguson
;-----------------------------------------------------------------------------

;
;program start
;
start:		mov	sp,offset stktop
		cld
		mov	ax,cs
		mov	ds,ax
		mov	[progseg],ax
		call	alloc				;allocate buffers
		jc	error
		call	init				;set global parameters
		call	getarg				;get filespec
		jc	error
		mov	es,[textseg]
		call	load				;load file
		jc	error
mainloop:	call	main				;process commands
		mov	dh,byte ptr [prmwinrow]		;to prompt/info row
		mov	dl,0				; column 0
		call	setcur				; set cursor
		mov	bh,[attrorg]			; original video attr
		call	clreol				; clear to end of line
		jmp	short finish			;normal exit
error:		mov	ds,cs:[progseg]			;error exit
		call	outmsg
finish:		mov	ax,4C00h			;exit program, rc=0
		int	21h

;
;critical error handler
;disk drive not ready or other unexpected (I/O) error
;
errtrap:	xpush	<ax,bx,dx>
		setsta	drwwin				;need redraw
		xor	dx,dx				;cursor at row 0, col 0
		call	setcur
		xpop	<dx,bx,ax>
		jmp	dword ptr cs:[i24vec]		;'Abort,Retry,Ignore?'

;
;ctr-break handler
;
breaktrap:	iret					;ignore ^C and ^Break

		page
;
;allocate buffers
;
;out:	flags	C = error
;	ds:si	error message address
;
alloc:		mov	bx,offset stktop		;free unused memory
		add	bx,15				;round up to segment
		mov	cl,4
		shr	bx,cl
		mov	ah,4Ah
		int	21h

		mov	bx,1000h			;64k text buffer
		mov	ah,48h
		int	21h
		jc	allocErr
		mov	[textseg],ax

		mov	bx,1000h			;64k block del buffer
		mov	ah,48h
		int	21h
		jc	allocErr
		mov	[cutseg],ax
		clc					;normal exit
		ret

allocErr:	mov	si,offset xrmem			;error exit
		stc
		ret

		page
;
;initialize global parameters
;
init:		mov	ax,3524h			;get int24h (crit err)
		int	21h
		mov	word ptr [i24vec+2],es		;save org int24h seg
		mov	word ptr [i24vec+0],bx		;save org int24h ofs

		mov	ax,2523h			;set int23h (ctr-break)
		mov	dx,offset breaktrap
		int	21h
		mov	ax,2524h			;set int24h (crit err)
		mov	dx,offset errtrap
		int	21h

		mov	ah,8				;get current video attr
		mov	bh,0				;page 0
		int	10h
		mov	[attrorg],ah

		staxz	<chrdelcnt,lindelcnt,blkdelcnt>
		stal	<txtchgsw,findstr,replstr,foptstr,lnrstr,fspblk>
		mov	es,ax				;video info dataseg

		mov	ax,word ptr es:[vidmaxcol]
		mov	[maxwincol],ax
		mov	ax,word ptr es:[vidabport]	;adapter base port
		add	ax,6				;adapter status port
		mov	[vidsta],ax
		jumpif	ax,e,vidstamono,init1
							;CGA or EGA:
		mov	byte ptr [attrnorm],attrnormcolor
		mov	byte ptr [attrhigh],attrhighcolor
		mov	byte ptr [attrinv],attrinvcolor
		mov	word ptr [vidseg],vidsegcolor	; adjust video seg
		mov	ax,1210h			; test EGA
		mov	bl,10h
		int	10h
		jumpif	bl,e,10h,initX
							;EGA:
		mov	al,byte ptr es:[egamaxrow]	; adjust row nrs
                xor     ah,ah
		mov	[prmwinrow],ax
		dec	ax
		mov	[stawinrow],ax
		dec	ax
		mov	[maxwinrow],ax
init1:							;MONOCHROME or EGA:
IF CGASNOW
		mov	word ptr [snowcheck],skipsnow	; no snow check
ENDIF
initX:		ret

		page
;
;get command argument
;
;out:	flags	C = error
;	ds:dx	error message address
;
getarg:		mov	si,offset cmdarg
		mov	bl,[si]
		xor	bh,bh
		mov	dx,offset xrfsp
		jumpif	bx,a,maxfsp,getargXC
		inc	si
		mov	byte ptr [bx+si],0		;make ASCIIZ

getarg1:	lodsb					;skip spaces
		ifspace	al,getarg1
		dec	si
		mov	di,offset fspmain		;copy filespec
		call	cpystrz
		clc					;normal return
		ret
getargXC:	stc					;error return
getargX:	ret

		page
;
;main processing loop
;
main:		iftrue	<byte ptr [endprgsw]>,getargX
		call	adjust
		mov	byte ptr [prvmrksw],false
		xor	ah,ah				;read keyboard char
		int	16h
		or	al,al				;extended keycode
		jnz	main1
		xchg	ah,al
		mov	si,offset exttbl
		call	docmd
		jmp	short main

main1:		mov	si,offset ctrtbl		;control char command
		call	docmd
		jnc	main

		call	isprint				;printable?
		jnc	main				;no : ignore
		call	inschr				;yes: insert character
		jmp	short main

;
;adjust display
;
adjust:		push	word ptr [msgptr]
		ifsta	updptr,<<call putwait>,<call adjptr>>
		ifsta	updrow,<<call putwait>,<call adjrow>>
		ifsta	updcol,<call adjcol>
		pop	word ptr [msgptr]

		ifsta	drwsta,<call putsta>
		ifsta	drwinf,<call putinf>
		ifsta	drwrow,<call putrow>

		mov	ah,01h				;read keyboard status
		int	16h
		jnz	adjustRet			;abort if key pressed

		ifsta	drwwin,<call putwin>
		ifsta	drwdwn,<call putdwn>
adjustRet:	jmp	setwincur

		page
;
;adjust text pointer to current row & columnn
;
adjptr:		ressta	updptr
		mov	si,[pnt.winref]			;si = window ref ptr
		mov	bx,[wintxtrow]			;bx = window top row
		mov	bp,[curtxtrow]			;bp = current row

		jumpif	bx,na,bp,adjptr2		;if window too far
		setsta	drwwin				; need redraw
adjptr1:	call	_prvsol				; repeat
		dec	bx				;  scroll window up
		jumpif	bx,a,bp,adjptr1			; until row in window

adjptr2:	mov	di,si				;di = window ref ptr
		mov	cx,bx				;cx = window top row
		mov	dx,bx				;dx = window end row
		add	dx,[maxwinrow]

adjptr3:	jumpif	bx,nb,bp,adjptr4		;while before text row
		call	_nxtsol				; next line
		jc	adjptr3a			; exit if eof
		inc	bx
		jumpif	bx,be,dx,adjptr3		; if window too low
		xchg	si,di				;  scroll window down
		call	_nxtsol
		xchg	si,di
		setsta	drwwin				;  need redraw
		inc	cx
		inc	dx
		jmp	short adjptr3

adjptr3a:	mov	[curtxtrow],bx			;past eof: adjust row
adjptr4:	mov	[pnt.winref],di			;set window ref ptr
		mov	[wintxtrow],cx			;set window top row

		xor	cx,cx				;cx = text col
		xor	dx,dx				;dx = disp col
		mov	bx,[virtxtcol]			;intended virtual col
adjptr5:	jumpif	cx,nb,bx,adjptr6
		call	_right
		jnc	adjptr5

adjptr6:	mov	[curtxtcol],cx			;adjust text col
		mov	[curdspcol],dx			;adjust disp col
		jumpif	dx,b,[windspcol],adjptr7	;check window bounds
		add	dx,2
		sub	dx,[maxwincol]
		jb	adjptr8
		jumpif	dx,b,[windspcol],adjptr8
adjptr7:	mov	[windspcol],dx			;adjust window
		setsta	drwwin				;need redraw
adjptr8:	mov	[pnt.curtxt],si			;set text ptr
		ret

		page
;
;adjust display row and text/display columns to text ptr
;
adjrow:		ressta	updrow
		mov	si,[pnt.winref]			;si = window ref ptr
		mov	bp,[pnt.curtxt]			;bp = current ptr
		mov	bx,[wintxtrow]			;bx = window top row

adjrow1:	jumpif	si,be,bp,adjrow2		;while window too far
		call	_prvsol				; scroll window up
		dec	bx
		setsta	drwwin				; need redraw
		jmp	short adjrow1

adjrow2:	mov	di,si				;di = window ref ptr
		mov	cx,bx				;cx = window top row
		mov	dx,bx				;dx = window end row
		add	dx,[maxwinrow]

adjrow3:	call	_geteol				;to end-of-line
		jc	adjrow4				;end-of-file: exit loop
		jumpif	si,nb,bp,adjrow4		;if before ptr
		call	_skfnwl				; to next line
		inc	bx
		jumpif	bx,be,dx,adjrow3a		; if window too low
		xchg	si,di				;  scroll window down
		call	_nxtsol
		xchg	si,di
		inc	cx
		inc	dx
		setsta	drwwin				;  need redraw
adjrow3a:	jumpif	si,b,bp,adjrow3			;loop if before ptr
		mov	[pnt.curtxt],si			;force ptr to sol

adjrow4:	mov	[curtxtrow],bx			;set text row
		mov	[pnt.winref],di			;set window ref ptr
		mov	[wintxtrow],cx			;set window top row
;;		jmp	short adjcol

		page
;
;adjust text/columns to text pointer within current display row
;text pointer is moved to eol if beyond current row
;
adjcol:		ressta	updcol
		mov	si,[pnt.curtxt]
		mov	di,si
		call	_getsol				;to start of line
		xor	cx,cx				;cx = text col
		xor	dx,dx				;dx = disp col
adjcol1:	jumpif	si,nb,di,adjcol2		;search current ptr
		call	_rightNotEof
		jnc	adjcol1
		mov	[pnt.curtxt],si			;ptr was beyond eol

adjcol2:	mov	[virtxtcol],cx
		mov	[curtxtcol],cx
		mov	[curdspcol],dx
		jumpif	dx,b,[windspcol],adjcol3	;check window bounds
		add	dx,2
		sub	dx,[maxwincol]
		jb	adjcolX
		jumpif	dx,b,[windspcol],adjcolX
adjcol3:	mov	[windspcol],dx			;scroll win left/right
		setsta	drwwin				;need redraw
adjcolX:	ret

;
;move right one character within current line, adjust text col and displ col
;
;in:	si	old text pointer
;	cx	old text col
;	dx	old display col
;out:	si	new text pointer
;	cx	new text col
;	dx	new display col
;	flags	C = end-of-line
;	al	skipped char if not eol
;
_right:		jumpif	si,nb,[pnt.endtxt],_rightXC
_rightNotEof:	mov	al,es:[si]
		caseal	cr,_rightXC
		caseal	lf,_rightXC
		caseal	ff,_rightXC
		ifntab	al,_right1
		or	cx,07h				;tab
		or	dx,07h
		jmp	short _right2
_right1:	ifnctrl	al,_right2
		add	dl,[ctrmode]			;control
		adc	dh,dh
		jmp	short _right3
_right2:	inc	dx				;other
_right3:	inc	cx
		inc	si
		clc
_rightX:	ret

_rightXC:	stc
		ret

		page
;
;process command
;
;in :	al	key code
;	si	command dispatch table offset
;out:	al	unchanged
;	carry	C  = no match
;		NC = match, command executed
;
docmd:		ifzero	<byte ptr [si]>,_rightXC	;test end of table
		mov	bx,[si]				;get start and end key
		add	si,2
		jumpif	al,b,bl,docmd1			;test range
		jumpif	al,na,bh,docmd2			;in range: process
docmd1:		sub	bh,bl				;not in range: try next
		mov	bl,bh
		mov	bh,0
		inc	bx
		add	si,bx
		add	si,bx
		jmp	short docmd

docmd2:		push	ax				;save char
		sub	al,bl				;compute offset
		mov	ah,0
		add	si,ax				;adjust pointer
		add	si,ax
		pop	ax				;restore character
		call	[si]				;process command
		clc					;report match
dmy:		ret					;(dummy command)

		page
;
;Subcommand processing
;
		ctrcmdx	ctrkcmd,ctrktbl			;^K commands
		ctrcmdx	ctrocmd,ctrotbl			;^O commands
		ctrcmd	ctrqcmd,ctrqtbl			;^Q commands
;;		jmp	short subcmd

;
;process subcommand
;
;in :	al	control character code
;	si	command table offset
;
subcmd:		push	si
		call	ctrprompt
		pop	si
		test	al,80h				;if extended
		jnz	subcmd3				; no echo

subcmd1:	call	toupper				;with/without Ctrl-key
		ifnctrl	al,subcmd2
		add	al,ctrl
subcmd2:	call	putnorm				;echo
subcmd3:	jmp	docmd				;process via table

;
;echo control-character as a prompt, get next key
;(mapping extended keycodes to 80h..8Fh)
;
;in :	al	control char code
;out:	al	next key code (possibly mapped)
;
ctrprompt:	setsta	drwinf
		mov	dh,byte ptr [prmwinrow]		;echo first ctrl char
		xor	dl,dl
		push	ax
		call	tovidofs
		mov	al,'^'
		call	putnorm
		pop	ax
		add	al,ctrl
		call	putnorm
		xor	ah,ah				;get second key
		int	16h
		and	al,al				;if extended keycode
		jne	ctrpromptX
		mov	al,ah				; map to 80h..8Fh
		or	al,80h
ctrpromptX:	ret

;--- END TEMAIN.ASM ----------------------------------------------------------
