[comp.sys.tandy] BCED - A Command EDitor for LS-DOS 6.2/6.3

laverman@prismab.prl.philips.nl (Bert Laverman) (10/26/88)

There doesn't seem to be happening much in this Newsgroup.
Since I recently finished this program - it will be published
in the paper of the Dutch TRS-80 users group - I thought it a good
idea to offer the program to the net-users as well.
I haven't noticed anything like 'moderating' (I'm new to
the net, maybe I missed something), so I'll just post it, and wait
to see what happens.

BCED is a Command Editor, to be run on a TRS-80 Model 4 using TRSDOS 6.2,
or LS-DOS 6.3. It was born from a feeling of frustration about the
severely inadequate possibilities for using 'old' commands, and for
editing while you type. BCED will allow you to do just that. Read the doc
file for more information.

Included are:
	bced.doc - the documentation
	bced.mac - the Macro-80 source file.

To compile the program, use the following commands:
	M80 BCED=BCED
	L80 BCED-N,-P:F600,BCED-E


>>>>> #include </standrard/disclaimer.h> <<<<<<

-----------------------------------------------------------------------
-- "You WORK here???" (security man, when confronted with my person) --
-----------------------------------------------------------------------


: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
echo 'Extracting bced.doc'
sed 's/^X//' > bced.doc << '+ END-OF-FILE bced.doc'
XBCED version 1.0 was written by B. Laverman.
XCopyright 1988 by Alphasoft Nederland, The Netherlands
X
XThis program is SHAREWARE. Please feel free to give your friends a copy.
XIf you like what you get, send a 5$ contribution (or an equivalent amount
Xin other currency) to:
X
X	B. Laverman
X	t.a.v. BCED projekt
X	p.a. Dilgtweg 14
X	9751 NG  Haren
X	The Netherlands
X
XNeither Alphasoft Nederland nor the author accepts liability for whatever
Xkind of damage resulting from the use of this program, or its source.
XIt SHOULD work on a TRS-80 Model 4 microcomputer, running TRSDOS 6.2
Xor LS-DOS 6.3. If it doesn't please report the bug as soon as possible
Xto me. I will try to correct it.
X
XDO NOT TRY TO CHANGE THE SOURCE!!! It is using inside information about
Xthe DOS (Try "The SOURCE" to find out what it does), and is therefore
XVERY SENSITIVE to even the smallest changes.
X
X
X		About BCED v1.0
X		===============
X
X  BCED is a Command Editor. It will patch itself into your DOS, modifying
Xthe @KEYIN SVC (on a veeery low level) to link through BCED. If a call
Xis made to the routine, it will check to see who made the call. If a JCL
Xfile is active, all activities will be done by the DOS. currently
XBCED only intercepts calls from the DOS Command Interpreter (SYS1/SYS),
Xand enhances the user interface. You can now:
X
X	- walk through your input line in a non-destructive way
X	- switch to an "insert mode" to insert text at any point
X	- delete single characters or the remainder of the line
X	- move the cursor fast to the next or previous "word"
X	- call up any of the last 16 commands entered, for editing
X	  and re-invoking.
X
X
X	  KeyBoard usage
X	  ==============
X
X	Left arrow	- move 1 character to the left (non-destructive)
X	Right arrow	- move 1 character to the right (non-destructive)
X	Up arrow	- recall previous command (cyclic)
X	Down arrow	- recall next command (cyclic)
X	Shift-Clear	- clear command line
X	Shift-Left ar	- go to the beginning of the line
X	Shift-Right ar	- go to the end of the line
X	Clear-Left ar	- go 1 word to the left
X	Clear-Right ar	- go 1 word to the right
X	Function key 1	- delete character under the cursor
X	Function key 2	- delete the remainder of the line
X	Function key 3	- toggle between insert and overwrite mode
X	Break		- good ol' <BREAK> works just fine.
X
X
X	  What is a "Word"?
X	  =================
X
X  Your TRS-80 being just a computer (with all due respect), it will not
Xbe able to recognize "words" as we humans do. BCED scans for a delimiter,
Xand will position itself just to the right of that delimiter and
Xany additional spaces.
X
X
X	  BCED and SYSGEN
X	  ===============
X
X  BCED will use the @ICNFG vector provided by DOS. This means you can
Xsafely SYSGEN your system with BCED in memory. On restart, BCED will be
Xreloaded in memory and - through @ICNFG - reinitialised.
X
X
X	  BCED and Bank-Switching
X	  =======================
X
X  BCED does not take memory-bank switching in account. I have only checked
XBCED together with the standard utility MEMDISK. No problems found so far.
XI suspect however, that any program calling @KEYIN from another bank than
Xbank 0, might cause a crash. Any hints on this point are appreciated.
X
X
X
XFrom the same author:
X	GPLUS for model I or III.
X  GPLUS will enhace you NEWDOS/80 V2 DiskBASIC with a multitude
Xof graphic features. For example:
X
X	- a virtual screen of (-32768,-32768) to (32767,32767)
X	- the (0,0) point where-ever you like
X	- absolute and relative coordinates
X	- 3-D drawing with perspective!
X	- 7 extra "screens" in memory, plus copy and mix commands
+ END-OF-FILE bced.doc
chmod 'u=rw,g=r,o=' 'bced.doc'
echo 'SENT: -rw-r-----  1 laverman     3521 Oct 26 16:35 bced.doc'
echo -n 'RCVD: '
/bin/ls -l bced.doc
echo 'Extracting bced.mac'
sed 's/^X//' > bced.mac << '+ END-OF-FILE bced.mac'
X; This is BCED version 1.0 - Finished 26 october 1988
X
X; Assemble with:
X;	m80 bced=bced
X;	l80 bced-n,-p:f600,bced-e
X; The program *should* work on a TRS-80 Model 4 using TRSDOS/LS-DOS 6.2
X; or 6.3. It detects older DOS versions. DOS+ however, is NOT detected.
X; Its effects on DOS+ are unknown. I only know it doesn't do what it's
X; supposed to do. The program uses *unportable* accesses to the DOS.
X; (I know it's a bad habit, but it was the only way to catch the
X; DOS input routine. The program will patch itself in the @ICNFG chain,
X; so feel free to use the SYSGEN command!
X
X; Copyright 1988 by Alphasoft Nederland, The Netherlands.
X; This program is "ShareWare". Feel free to give your friends a copy.
X; If you like what you get, please send a $5 contribution (or equivalent
X; amount in other currency) to:
X;	B. Laverman
X;	t.a.v. BCED projekt
X;	p.a. Dilgtweg 14
X;	9751 NG	Haren (Gn)
X;	The Netherlands
X
X
X; Here come some DOS SVC numbers, and the 
X@dsply	equ	10	; DOS print string
X@abort	equ	21	; set return value -1, then ...
X@exit	equ	22	;	exit to dos
X@high$	equ	100	; get/set protected memory area
X@flags	equ	101	; get system flags pointer
X
X	cseg		; could've done "aseg" and then "org 0f600h"
X
X
X; init - dos checking + initialization
Xinit:	ld	a,@flags	; get @FLAGS pointer
X	rst	28h
X	ld	a,(iy+27)	; check DOS version
X	cp	62h		; TRSDOS 6.2 is ok
X	jr	z,osok
X	cp	63h		; LS-DOS 6.3 also
X	jr	z,osok
X	ld	hl,.oserr	; anything else is considered unsafe
X	ld	a,@dsply	; print string
X	rst	28h
X	ld	a,@abort
X	rst	28h
X
X; halt is for when you really sc*w things up.
Xhalt:	ld	a,@dsply	; print errormessage
X	rst	28h
X	ld	hl,.reset	; followed by this
X	ld	a,@dsply
X	rst	28h
X	di
X	jr	$		; Use RESET to restart
X
Xosok:	bit	0,(iy+2)	; memory fixed?
X	ld	hl,.mmer1
X	jr	nz,halt		; stop if so
X	ld	hl,0		; get current HIGH$
X	ld	b,0
X	ld	a,@high$
X	rst	28h
X	inc	hl		; was it 0FFFFH?
X	ld	a,h
X	or	l
X	ld	hl,.mmer2
X	jr	nz,halt		; stop if not
X
X	ld	hl,header-1	; set new HIGH$
X	ld	b,0
X	ld	a,@high$
X	rst	28h
X
X	call	entry		; initialise the routine
X	ld	a,(iy+28)	; copy current @icnfg vector
X	ld	(link),a
X	ld	a,(iy+29)
X	ld	(link+1),a
X	ld	a,(iy+30)
X	ld	(link+2),a
X	ld	(iy+28),0c3h		; patch in our new JumP
X	ld	(iy+29),LOW entry	; (plus the address)
X	ld	(iy+30),HIGH entry
X
X	ld	hl,0
X	ld	a,@exit		; back to DOS
X	rst	28h
X
X.oserr:	db	'Use TRSDOS/LS-DOS 6.2 en 6.3 for BCED!!!',13
X.mmer1:	db	'*** HELP!!! Memory was FIXED!!',13
X.mmer2:	db	'*** Darn! BCED just overwrote something else in High Memory!'
X	db	13
X.reset:	db	'*** Use RESET to restart.',13
X
X
Xmaxcom	equ	16		; # of commands to remember. (Don't change)
Xmaxlen	equ	80		; Max lengthof a command.	(Idem)
X
Xcflag$	equ	006ch		; horrible! memory poking! Keep off!!
Xsflag$	equ	007ch
X$$kbd	equ	0628h
X$$dsp	equ	0642h
X$$dsply equ	052dh
X$$vdctl equ	0d42h
X
X
X; First comes a standard memory Header.
Xheader:	jr	entry		; jr to the initialization code
X	dw	last		; last byte used
X	db	9,'BCED v1.0'	; the name
X
X.title:	db	'BCED --- Bert''s Command EDitor v1.0 --- 26 October 1988',10
X	db	'(c) 1988 by Alphasoft',13
X
X; The initalization
Xentry:	ld	hl,.title	; Send out the title
X	ld	a,@dsply
X	rst	28h
X
X	ld	hl,$keyin	; Install our new @KEYIN
X	ld	(21h),hl	;  (we use the RST 20H vector)
X	ld	a,0c3h		;  (this is a JP)
X	ld	(20h),a
X	ld	a,0e7h		;  (this is a RST 20H)
X	ld	(0585h),a
X
X	ld	hl,buffer	; empty the buffer
X	ld	de,buffer+1
X	ld	bc,maxcom*maxlen-1
X	ld	(hl),3
X	ldir
X
X        xor     a		; reset
X        ld      (curcom),a	;  current use buf # and
X        ld      (curcom+1),a	;  current scan buf #
X
X	ret			; Here @ICNFG is patched
X	db	0,0
Xlink	equ	$-3
X
X; gaddr - returns the address of line buffer (A) in HL
Xgaddr:	push	de		; save DE
X	ld	l,a		; HL := buffer #
X	ld	h,0
X	add	hl,hl		; HL := # * 2
X	add	hl,hl		;	  * 4
X	add	hl,hl		;	  * 8
X	add	hl,hl		;	  * 16
X	ld	e,l		; (DE:= # * 16)
X	ld	d,h
X	add	hl,hl		; HL := # * 32
X	add	hl,hl		;	    64
X	add	hl,de		;	    80
X	ld	de,buffer	; start of buffer
X	add	hl,de
X	pop	de		; restore de
X	ret
X
X; handle - take care of a keystroke
Xhandle:	or	a		; what kind of key?
X	jp	m,func		; jump if poss. Function key
X	cp	' '		; Control code?
X	jr	c,cntl		;  jump if so
X	ld	(ix+_buf),a	; normal key, store temporarely
X	ld	a,(ix+_ins)	; insert mode on?
X	or	a
X	jr	nz,insert	;  if so, jump
X
Xnormal:	ld	a,(hl)		; check buffer
X	cp	3		; end of line?
X	jr	nz,noinc	;  if not, skip length check
X	ld	a,(ix+_len)	; see if we're within limits
X	cp	(ix+_max)
X	jr	nc,nodsp	;  if not, skip
X	inc	(ix+_len)	; increment length count
Xnoinc:	ld	a,(ix+_buf)	; get character
X	ld	(hl),a		; put it in buffer
X	inc	hl		; increment pointer
X	call	$$dsp		; put character on screen
X	inc	(ix+_pos)	; increment pos count
X
Xnodsp:	or	1		; set "nz" condition
X	ret			; finished
X
X; insert - insert the given character
Xinsert:	ld	a,(ix+_len)	; space left?
X	cp	(ix+_max)
X	jr	nc,nodsp	;  if not, jump
X	inc	(ix+_len)	; increment linelength
X	inc	(ix+_pos)	; 1 pos to the right
X	ld	c,(ix+_buf)	; get character to C
X	push	hl		; save current buffer pos
X
Xinslp:	ld	a,(hl)		; get character from buffer
X	ld	(hl),c		; insert previous
X	push	af		; save AF and BC
X	push	bc
X	ld	a,c		; character to A
X	call	$$dsp		; print it
X	pop	bc		; restore BC and AF
X	pop	af
X	cp	3		; end of line?
X	jr	z,insf		;  if so, jump.
X	inc	hl		; next pos
X	ld	c,a		; currect char -> previous
X	jr	inslp		; Loooop
X
Xinsf:	pop	hl		; restore buffer pos
X	inc	hl		; 1 pos to the right
X	jp	cpos		; set the cursor
X
X; cntl - handle control codes
Xcntl:	cp	13		; is it <ENTER>?
X	ret	z		;  if so, finished!
X	sub	8		; is it "<-"?
X	jp	z,left		;  if so, jump
X	dec	a		; is it "->"?
X	jp	z,right		;  if so, jump
X	dec	a		; is it down-arrow?
X	jp	z,next
X	dec	a		; up-arrow?
X	jp	z,prev
X	sub	13		; skip some unused codes
X	ret	c		;  if so, finished
X	jp	z,sh_l		;  <SHIFT>-"<-"?
X	dec	a		; <SHIFT>-"->"?
X	jp	z,sh_r
X	sub	6		; <SHIFT>-<CLEAR>?
X	jp	z,sh_c
X
X	or	1		; unknown key, finished
X	ret
X
X; func - handle Function keys & <CLEAR>+anything
Xfunc:	cp	81h		; is it F1?
X	jr	z,func_1
X	cp	82h		; F2?
X	jr	z,func_2
X	cp	83h		; F3?
X	jr	z,func_3
X	cp	88h		; <CLEAR>-"<-"?
X	jp	z,l_word
X	cp	89h		; <CLEAR>-"->"?
X	jp	z,r_word
X
X	ret			; unknown key, finished
X
X; F1 - delete current character
Xfunc_1:	push	hl		; save current buffer-pos.
X	ld	a,(hl)		; something available to delete?
X	cp	3
X	jr	z,ffin		; if not, jump
X	dec	(ix+_len)	; decrement length
X	ld	a,30		; clear to end-of-line on screen
X	call	$$dsp
Xf1lp:	inc	hl		; move 1 char. left
X	ld	a,(hl)
X	dec	hl
X	ld	(hl),a
X	inc	hl
X	cp	3		; end of line?
X	jr	z,cpos1		;  if so, jump
X	call	$$dsp		;  else, print character
X	jr	f1lp		; loooop
X
X; F2 - delete to end-of-line
Xfunc_2:	push	hl		; save current buffer-pos.
X	ld	a,30		; clear to end-of-line on screen
X	call	$$dsp
X	ld	a,(ix+_pos)	; update length
X	ld	(ix+_len),a
Xf2lp:	ld	a,(hl)		; check buffer
X	cp	3		; end of line?
X	jr	z,ffin		;  if so, finished
X	ld	(hl),3		; erase character
X	inc	hl		; next
X	jr	f2lp		; looop
X
Xffin:	pop	hl		; restore hl
X	or	1		; finished
X	ret
X
X; F3 - toggle insert mode
Xfunc_3:	ld	a,(ix+_ins)	; get current setting
X	cpl			; invert (0 -> -1, -1 -> 0)
X	ld	(ix+_ins),a
X	or	a
X	jr	z,f3norm	; skip if now in normal mode
X	ld	c,143		; block-cursor for insert mode
X	jr	f3set
Xf3norm:	ld	c,'_'		; normal cursor for normal mode
Xf3set:	ld	b,8
X	call	$$vdctl		; (@VDCTL, B=8, C=Cursor character)
X	or	1		; finished
X	ret
X
X; cpos/cpos1 - move cursor to current pos, with/without HL save.
Xcpos:	push	hl		; save hl
Xcpos1:	ld	b,4		; ask cursor pos
X	call	$$vdctl		; (@VDCTL, B=4, result in HL)
X	ld	l,(ix+_pos)	; h-line, l-column
X	ld	b,3		; set new pos
X	call	$$vdctl		; (@VDCTL, B=3, pos in HL)
X	pop	hl		; restore hl
X	or	1		; finished
X	ret
X
X; r_word - skip to next "word" to the right
Xr_word:	ld	a,(ix+_pos)	; allready at the end?
X	cp	(ix+_len)
X	jr	z,rwfin		; if so, finished
X	inc	(ix+_pos)	; increment pos count
X	inc	hl		; increment bufferpointer
X	ld	a,(hl)		; get character
X	cp	' '		; space?
X	jr	z,rwst		;  if so, finished
X	cp	','		; comma also ok
X	jr	z,rwst
X	cp	'('		; or this
X	jr	z,rwst
X	cp	'.'		; or this
X	jr	z,rwst
X	cp	'/'		; or this
X	jr	nz,r_word	; loooop
X
Xrwst:	ld	a,(ix+_pos)	; end of line?
X	cp	(ix+_len)
X	jr	z,rwfin		; if so, finished
X	inc	(ix+_pos)	; skip delimiter
X	inc	hl
X	ld	a,(hl)		; see what's next
X	cp	' '		; a space?
X	jr	z,rwst		;  if so, skip it as well
X
Xrwfin:	jp	cpos		; finished, set cursor
X
X; l_word - skip a "word" to the left
Xl_word:	ld	a,(ix+_pos)	; at the start of the line?
X	or	a
X	jr	z,lwfin		; if so, finished
X	dec	(ix+_pos)	; 1 pos to the left
X	dec	hl
Xlwlp:	ld	a,(ix+_pos)	; begin of line reached?
X	or	a
X	jr	z,lwfin		; if so, finished
X	dec	(ix+_pos)	; nog 1 pos to the left
X	dec	hl
X	ld	a,(hl)		; get character
X	cp	' '		; see r_word for comments
X	jr	z,lwst
X	cp	','
X	jr	z,lwst
X	cp	'('
X	jr	z,lwst
X	cp	'.'
X	jr	z,lwst
X	cp	'/'
X	jr	nz,lwlp
Xlwst:	inc	(ix+_pos)	; 1 pos to the right
X	inc	hl
Xlwfin:	jp	cpos		; move cursor
X
X; left - handle left-arrow
Xleft:	ld	a,(ix+_pos)	; can we go further left?
X	or	a
X	jr	z,lret		;  if not, finished
X	dec	(ix+_pos)	; go 1 to the left
X	dec	hl
X	ld	a,24		; on screen
X	call	$$dsp
Xlret:	or	1
X	ret
X
X; right - handle right-arrow
Xright:	ld	a,(hl)		;Can we go further right?
X	cp	3
X	jr	z,rret		;  if not, finished
X	inc	hl		; go 1 to the right
X	inc	(ix+_pos)
X	ld	a,25		; on screen
X	call	$$dsp
Xrret:	or	1
X	ret
X
X; prev - handle up-arrow
Xprev:	ld	a,(ix+_sca)	; get "scan" buffer #
X	dec	a		; 1 backward
X	and	00001111b	; modulo 16!
X	ld	(ix+_sca),a	; store new scan nr.
X	jr	z,dspcom	; if #==0, than use anyway
X	call	gaddr		; get buffer address
X	ld	a,(hl)		; look if something is present
X	cp	3
X	jr	z,prev		;  if not, try next
X	jr	dspc1		; use this buffer
X
X; next - handle down-arrow
Xnext:	ld	a,(ix+_sca)	; get "scan" buffer #
X	inc	a		; 1 forward
X	and	00001111b	; modulo 16
X	ld	(ix+_sca),a	; store #
X	jr	z,dspcom	; if #==0, then use anyway
X	call	gaddr		; get buffer address
X	ld	a,(hl)		; look if something present
X	cp	3
X	jr	z,next		;  if not, next
X	jr	dspc1		; use this one
X
X; dspcom/dspc1 - display current scan buffer contents& copy them
X; to the use buffer.
Xdspcom:	call	gaddr		; get scan buffer address
Xdspc1:	ld	a,29		; clear screen line
X	call	$$dsp
X	ld	a,30
X	call	$$dsp
X	call	$$dsply		; print buffer contents
X	ex	de,hl		; buffer address to DE
X	ld	a,(ix+_cur)	; get current use buffer #
X	call	gaddr		; get address
X	call	clear		; empty use buffer
X	ex	de,hl		; scan buffer to HL, current to DE
X	ld	b,0		; length comes in B
Xdspcl:	ld	a,(hl)		; get character
X	cp	3		; end-of-line?
X	jr	z,dspcf		;  if so, finished
X	ld	(de),a		; copy character
X	inc	hl		; increment pointers
X	inc	de
X	inc	b		; increment length
X	jr	dspcl		; looop
Xdspcf:	ex	de,hl		; buffer pos to hl
X	ld	(ix+_pos),b	; store length
X	ld	(ix+_len),b
X	or	1		; finished
X	ret
X
X; sh_l - handle <SHIFT>-Left arrow
Xsh_l:	ld	e,(ix+_pos)	; get current pos
X	ld	d,0
X	or	a
X	sbc	hl,de		; rewind to start of line
X	ld	(ix+_pos),d	; reset pos
X	jp	cpos		; move cursor
X
X; sh_r - handle <SHIFT>-right arrow
Xsh_r:	ld	a,(ix+_len)	; get length
X	ld	e,a		; store in E
X	sub	(ix+_pos)	; compute remaining length
X	ld	(ix+_pos),e	; set newpos
X	ld	e,a		; Fast-Forward in buffer
X	ld	d,0
X	add	hl,de
X	jp	cpos		; move cursor
X
X; sh_c - handle <SHIFT>-clear
Xsh_c:	ld	e,(ix+_pos)	; rewind to start of buffer
X	ld	d,0
X	or	a
X	sbc	hl,de
X	ld	(ix+_pos),d	; reset pos
X	ld	(ix+_len),d	; reset length
X	ld	a,29		; Clear line on screen
X	call	$$dsp
X	ld	a,30
X	call	$$dsp
X	call	clear		; clear buffer
X	or	1		; finished
X	ret
X
X; clear - fill the given buffer with CHR$(3)'s
Xclear:	push	hl		; save hl
X	ld	b,maxlen
X	ld	a,3
Xclrlp:	ld	(hl),a		; clear a character
X	inc	hl		; increment pointer
X	djnz	clrlp		; loooop
X	pop	hl		; restore hl
X	ret
X
X; $keyin - our new input routine
X
X$keyin:	pop	de		; get return-address
X	push	hl		; We overwrote this one with a RST 20H.
X	push	de		; push return address
X	ld	a,(cflag$)	; was it DOS calling?
X	and	00000100b
X	ret	z		; if not, return
X	ld	a,(sflag$)	; Job Control executing?
X	and	00100000b
X	ret	nz		; if so, return
X
X	pop	de		; remove return address
X	push	ix		; save ix
X	ld	ix,curcom
X	ld	a,b		; how many character were asked?
X	cp	maxlen		; clip to maxlen-1 if necessary
X	jr	c,noclip
X	ld	a,maxlen-1
Xnoclip:	ld	(ix+_max),a	; store it
X	ld	(bufad),hl	; store buffer address
X	ld	a,(ix+_cur)	; get current buffer #
X	ld	(ix+_sca),a	; make it also the scan buffer
X	call	gaddr		; get buffer address
X	call	clear		; empty buffer
X	ld	(ix+_len),0	; init some things
X	ld	(ix+_pos),0
X	ld	(ix+_ins),0
X
Xinplp:	call	$$kbd		; wait for a key
X	cp	80h		; is it <BREAK>?
X	jr	z,break		; if so, jump
X	call	handle
X	jr	nz,inplp	; loop while no <ENTER> pressed
X
X	ld	b,(ix+_len)	; get actual length
X	ld	(ix+_pos),b	; move cursor
X	call	cpos
X	ld	a,13		; <ENTER> to the screen
X	call	$$dsp
X	ld	a,(ix+_cur)	; get buffer address
X	call	gaddr
X	ld	de,(bufad)	; get dest. buffer address
X	ld	a,(ix+_len)	; length to a
X	or	a		; length 0?
X	jr	z,nocopy	;  if so, skip
X	ld	c,a		; length to bc
X	ld	b,0
X	ldir			; copy buffer
X
Xnocopy:	ld	a,13		; insert <ENTER>
X	ld	(de),a
X
X	ld	a,(ix+_cur)	; update use buffer #
X	inc	a
X	and	00001111B
X	ld	(ix+_cur),a
X
X	ld	b,8		; set cursor to a '_'
X	ld	c,'_'
X	call	$$vdctl
X
X	ld	b,(ix+_len)	; actual length in b
X	pop	ix		; restore registers
X	pop	hl
X	xor	a		; set NC condition
X	ret
X
Xbreak:	ld	a,13		; <BREAK>! print an <ENTER>
X	call	$$dsp
X	pop	ix		; restore registers
X	pop	hl
X	ld	(hl),13		; buffer is empty
X	ld	b,0
X	scf			; set C flag
X	ret
X
X
Xbuffer:	ds	maxlen * maxcom
X	db	3
X
X_cur	equ	0
X_sca	equ	1
X_pos	equ	2
X_buf	equ	3
X_max	equ	4
X_len	equ	5
X_ins	equ	6
X
Xcurcom:	db	0	; ix+_cur
X	db	0	; ix+_scan
X	db	0	; ix+_pos
X	db	0	; ix+_cbuf
X	db	0	; ix+_max
X	db	0	; ix+_len
X	db	0	; ix+_ins
X
Xbufad:	dw	0
X
Xlast	equ	$-1	; the last address used by BCED
X
X	end	init
+ END-OF-FILE bced.mac
chmod 'u=rw,g=r,o=' 'bced.mac'
echo 'SENT: -rw-r-----  1 laverman    13490 Oct 26 16:35 bced.mac'
echo -n 'RCVD: '
/bin/ls -l bced.mac
exit 0