home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
turbodsg
/
fanled.mqc
/
FANLED.MAC
Wrap
Text File
|
1986-07-05
|
14KB
|
724 lines
; FANLED - FANcy Line EDitor for TurboDOS 1.4x
;
; RELEASE VERSION HISTORY
; 1.00 04/02/85 changed kill buffer logic to retain last kill buffer
; contents until ^K or ^X (rather than erasing at the
; beginning of each edit session). This now allows
; use of the kill buffer as "storage" for a frequently
; used command.
; 1.10 04/05/85 Optimized code for size
; 1.11 fixed quote problem
; 1.20 04/09/85 Made edit keys global
; 1.30 05/04/85 Fixed problem in ^Y routine
;
name ('FANLED')
;
; Input:
; HL points to a data structure:
; <HL> = CLBLEN (command line buffer length
; <HL+1> = actual command line length
; <HL+2> = first byte of null-terminated command line
; Output:
; HL = pointer to actual command line length
; A = actual command line length
;
.z80
;
; Externals used:
;
extrn dms,echo,conin,conout
;
; Global entry point:
;
public inpln
;
; Global patch point:
;
public forspc
;
; command character equates
;
beglin equ 'A'-40h ; ^A - beginning of line
backch equ 'B'-40h ; ^B - cursor backwards
delfor equ 'D'-40h ; ^D - delete char forward
endlin equ 'E'-40h ; ^E - end of line
forwch equ 'F'-40h ; ^F - cursor forward
delbak equ 'H'-40h ; ^H - delete char backward
kilfor equ 'K'-40h ; ^K - kill forward
quote equ 'Q'-40h ; ^Q - quote next char
recall equ 'R'-40h ; ^R - recall previous command line
abort equ 'U'-40h ; ^U - abort line
kilbak equ 'X'-40h ; ^X - kill backward
yank equ 'Y'-40h ; ^Y - yank (unkill)
delete equ 7fh ; DEL- same as ^H
;
; other equates
;
cr equ 0dh ; carriage return
bell equ 7 ; bell character
litc equ '^' ; caret (prefix for control char display)
;
; data storage areas
;
dseg
;
forspc: db 'L'-40h ; nondestructive forward space character
qflag: db 0ffh ; quote next flag
clsave: dw 0 ; command line structure pointer save
clen: db 0 ; command line length
insy: db 0 ; insert yank flag
killen: db 0 ; length of kill buffer
kilbuf: ds 162 ; 162 byte kill buffer
oldlin: ds 162 ; old command line
;
; command table
;
cmdtbl:
fanbg:: db beglin
dw cbegli
fanbk:: db backch
dw cbackc
fanel:: db endlin
dw cendli
fanfc:: db forwch
dw cforwc
fandf:: db delfor
dw cdelfo
fandb:: db delbak
dw cdelba
fankf:: db kilfor
dw ckilfo
fanqu:: db quote
dw cquote
fanrc:: db recall
dw crecal
fankb:: db kilbak
dw ckilba
fanya:: db yank
dw cyank
fanab:: db abort
dw cabort
db delete
dw cdelba
db cr
dw exit
ncmds equ ($-cmdtbl)/3 ; number of commands
;
cseg
;
; REGISTER USAGE:
; HL normally points to the current character in the command line
; unless used otherwise
; DE normally points to the kill buffer or the old line buffer
; B always holds the current byte count for the main command line
; C always holds the current cursor position in the command line
; A usually holds a byte received from the keyboard and/or echoed
;
; SUBROUTINES:
;
; GETCH - get character in A, preserve all regs
;
getch: push bc
push de
push hl
call conin
jr popr
;
; BKSPC - backspace
;
bkspc: ld a,delbak
;
; PUTCH - display character in A, preserve all regs
;
putch: push bc
push de
push hl
ld c,a
push af
call conout
pop af
popr: pop hl
pop de
pop bc
ret
;
; ERROR - ring the bell
;
error: ld a,bell
jr putch
;
; DELLFT - delete left character with pointer movement
; assume: HL points into command line, B holds
; current byte count
;
dellft: dec b ; decrement count
dec c ; decrement cursor pointer
dec hl ; decrement pointer
ld a,(hl) ; get byte
cp ' ' ; if control...
jr nc,delchl ; delete one char if no control
inc d ; increment control char counter
call delchl
;
; DELCHL - delete left character (bs,sp,bs)
;
delchl: push bc
push de
push hl
call dms
db 8,' ',88h
jr popr
;
; GETCMD - A=character, determine if it's an edit command
;
getcmd: push hl
push bc
cp cr
jr z,iscr
ld hl,qflag
bit 0,(hl)
set 0,(hl)
jr z,getcmx
iscr: ld b,ncmds
ld hl,cmdtbl ; point to command table
getcml: cp (hl)
jr z,gotcmd ; got a command
inc hl
inc hl
inc hl
djnz getcml ; keep searching
ld b,a
xor a ; set zero flag
ld a,b
jr getcmx ; exit
;
gotcmd: inc hl
ld e,(hl)
inc hl
ld d,(hl)
xor a
inc a ; reset zero flag
getcmx: pop bc
pop hl
ret
;
;
; MAIN PROGRAM ENTRY POINT
;
;
inpln: xor a ; zero byte count/cursor buffer
ld b,a
ld c,a
dec a
ld (qflag),a ; reset quote flag
ld a,(hl) ; get max byte count
inc hl ; point to current byte count
ld (clsave),hl ; save pointer
ld (hl),0 ; be sure command line is empty
inc hl ; point to first char of command line
ld (clen),a ; store max command line length
;
; this is the main loop
;
getnxt: call getch ; get a character
call getcmd ; check if command, return zero if not
jr z,ascii ; no command, enter it into cmd line
push de ; jump to de
ret
;
; enter A into command line, echo character
;
ascii: push af
ld a,(clen) ; get max line length
cp b ; reached?
jr nz,nolov ; nope
pop af
call error ; else beep
jr getnxt ; and try again
;
nolov: ld a,c ; see if at end of line
cp b
jr nz,insert ; inside line, so do insert mode
pop af
ld (hl),a
inc hl ; increment
inc b ; pointers
inc c
call outch
jr getnxt ; go get another
;
; INSERT - insert a character, move all others right
;
insert: ld a,(clen) ; get allowed length
cp b
jr nz,insne
call error ; complain
pop af
jr getnxt ; and exit if too long
;
insne: ld a,b ; get total chars in line
sub c ; subtract cursor position
push bc ; save pointers
ld c,a ; set counter
ld b,0 ; bc=number of bytes right of cursor
add hl,bc ; point to end of line
ld d,h ; duplicate in de
ld e,l
inc de ; de points past line
inc bc
inc bc
lddr ; move line up one char
inc hl
pop bc ; get counters back
inc b ; increment cursor and count
inc c
pop af ; now get character
inc hl ; increment pointer
ld (hl),a ; save it in command line
push hl ; save pointer
push bc ; save counters
ld a,b
sub c ; count again
inc a
ld b,a
ld c,a
ld a,(hl) ; compensate if ctl char inserted
cp ' '
jr nc,insl
dec c
insl: ld a,(hl)
cp ' '
jr nc,insnc
inc c
insnc: call outch ; disply the char
inc hl
djnz insl
;
insd: ld b,c
dec b
insdl: call bkspc
djnz insdl
;
inse: pop bc
pop hl
inc hl
jp getnxt
;
; OUTCH - output a character, display control char if necessary
;
outch: cp ' ' ; check if ctl character
jr nc,noctl ; skip if not
push af ; save char
ld a,litc ; prefix char
call putch ; display it
pop af ; get char back
add a,40h ; make it alpha
noctl: jp putch ; display char
;
;
; COMMAND PROCESSOR ROUTINES
;
; CR typed -- exit back to turbodos
;
exit: ld a,c ; see if we're at end of line
cp b ; if so continue
jr z,cntxit
inc hl ; else up pointers
inc c
jr exit
;
cntxit: ld (hl),0 ; terminate command line
push bc
ld a,cr
call echo ; echo the RETURN
pop bc
ld hl,(clsave) ; get command line pointer
ld (hl),b ; save actual byte count
push hl ; save
push bc ; registers
ld c,b ; set up count
ld b,0
inc c
ld de,oldlin ; point to previous line buffer
ldir ; store current line there
pop bc ; get regs back
pop hl
ld a,b ; byte count in A
ret
;
;
; CBEGLI - go to beginning of line
;
cbegli: inc c ; set up cursor pointer
cbegl1: dec c ; decrement cursor ptr
jr z,..gn1 ; until zero
call bkspc
dec hl
ld a,(hl)
cp ' '
call c,bkspc
jr cbegl1
;
; CENDLI - go to end of line
;
cendli: ld a,c ; get cursor
cp b ; if cursor at end of line
jr z,..gn1 ; then get next char
inc c ; point to next char
ld a,(hl)
inc hl
cp ' '
ld a,(forspc)
call c,putch
call putch
jr cendli ; and so on
;
; CBACKC - back 1 char
;
cbackc: ld a,c ; get count
or a ; if at left
jr z,..gn1 ; do nothing
call bkspc ; else backspace
dec c ; decrement counter
dec hl ; pointer
ld a,(hl)
cp ' '
call c,bkspc
jr ..gn1
;
; CFORWC - forward 1 char
;
cforwc: ld a,c ; get count
cp b ; if at end
jr z,..gn1 ; do nothing
inc c ; increment counter
ld a,(hl)
cp ' '
ld a,(forspc)
call c,putch
call putch ; move cursor
inc hl ; pointer
..gn1: jp getnxt
;
; CQUOTE - do next char literally
;
cquote: xor a
ld (qflag),a
jr ..gn1
;
; CRECAL - recall previous command line
;
crecal: inc b ; test if b=0
dec b
jr nz,..gn1 ; count must be 0
ld a,(oldlin) ; anything in?
or a
jr z,..gn1 ; no, empty
push hl
ld de,oldlin ; get old line
ex de,hl ; set up for move
dec de
ld c,(hl)
ld b,0
push bc
inc c
ldir
pop bc
ld b,c ; get count into b
pop hl ; get pointer
dslp: ld a,(hl) ; get byte
call outch ; display it with ctl char expansion
inc hl ; point to next
djnz dslp ; until all done
ld b,c ; count = cursor
jr ..gn1 ; exit
;
; CDELBA - delete previous character, move following chars to left
;
cdelba: ld a,c ; see if at start of line
or a
jr z,..gn2
ld de,0
call dellft ; delete char to the left
ld a,b
cp c
jr z,..gn2
jr movdel ; move after delete
;
; CDELFO - delete following character, move remainder left
;
cdelfo: ld a,c ; if cursor at right end
cp b
jr z,..gn2 ; then do nothing
ld de,0
dec b
movdel: ld a,b ; see if end of line
push bc ; save counters
push hl ; save line ptr
sub c ; a=number of chars
push af
inc a
ld c,a
ld b,0
push de ; save control char count
ld d,h
ld e,l
inc hl
ldir
pop de ; get control char count (0/1)
pop af ; get byte count
pop hl ; get line pointer
push hl ; save it again
ld b,a
or a
jr nz,mvdell
ld a,' '
call putch
call putch
call bkspc
call bkspc
jr mvdelq
;
mvdell: ld a,(hl)
cp ' '
jr nc,mvd1
inc e
mvd1: call outch
inc e ; increment char count
inc hl
djnz mvdell
ld a,' '
call putch ; wipe out last char
call putch
call bkspc
mvdel1: ld b,e
call bkspc
mvdel2: call bkspc
djnz mvdel2
mvdelq: pop hl
pop bc
..gn2: jp getnxt
;
; CKILFO - kill all chars forward
;
ckilfo: ld a,b
cp c
jr z,..gn2 ; nothing to kill
sub c ; get byte count
ld b,c
push bc ; save count, cursor
ld (killen),a ; store kill buffer length
ld c,a
ld b,0
push bc
push hl ; save line pointer
ld de,kilbuf
ldir ; move into kill buffer
pop hl
pop bc
push hl
ld b,c
ckilf1: ld a,(hl)
inc hl
cp ' '
ld a,' '
jr nc,ckilf2
call putch
inc c
ckilf2: call putch
djnz ckilf1
ld b,c
ckilf3: call bkspc
djnz ckilf3
pop hl
pop bc
ld (hl),0
jr ..gn2
;
; CKILBA - kill all chars backward
;
ckilba: ld a,c
or a
jr z,..gn2 ; nothing to kill
push bc ; save counters
push hl ; save pointer
ld de,(clsave) ; get pointer to start
inc de
or a
sbc hl,de ; hl is now length
ld b,h
ld c,l
ld hl,killen ; point to kill buffer
ld (hl),c
inc hl
ex de,hl
ldir ; move stuff into kill buffer
pop hl ; get old ptr
pop bc
push bc
push hl
ckilb1: dec hl
ld a,(hl)
cp ' '
ld a,8
call c,putch
call putch
dec c
jr nz,ckilb1
ld e,0
ckilb2: ld a,(hl)
inc hl
cp ' '
ld a,' '
jr nc,ckilb3
call putch
inc e
ckilb3: call putch
inc e
djnz ckilb2
ld b,e
ckilb4: call bkspc
djnz ckilb4
pop hl ; get line ptr
pop bc ; get counters
ld a,b
sub c ; a now has byte count
ld c,a
ld b,0
push bc
inc bc
ld de,(clsave)
inc de
push de
ldir
pop hl
pop bc
ld b,c
ld c,0
ld a,b
or a
jr z,..gn3
push hl
push bc
ld e,0
ckilb5: ld a,(hl)
cp ' '
jr nc,ckilb6
inc e
push af
ld a,litc
call putch
pop af
add a,40h
ckilb6: call putch
inc e
inc hl
djnz ckilb5
ld b,e
ckilb7: call bkspc
djnz ckilb7
pop bc
pop hl
..gn3: jp getnxt
;
; CYANK - yank kill buffer to current cursor
;
cyank: ld a,(killen) ; get kill buffer length
or a
jr z,..gn3 ; kill buffer empty
add a,b ; check total size
jr c,er1 ; gee, much too much (>256)!
ld e,a
ld a,(clen)
cp e
jr nc,yntl ; go ahead if not too long
er1: call error ; too long
jr ..gn3
;
yntl: xor a
ld (insy),a
ld a,b
cp c ; check if cursor at end of line
ld a,(killen) ; get length of kill buffer
jr z,nomove ; skip if at end of line
push bc ; save count
push hl ; save pointer
ld e,a
ld d,0 ; de = number of bytes to be freed
ld a,b
sub c ; a has bytes to be moved
ld c,a
ld b,0 ; bc has bytes tbm
add hl,bc ; point to end of line
push hl
add hl,de ; point to new end of line
ex de,hl
pop hl
inc bc
inc bc
lddr
pop hl
pop bc
ld a,0ffh
ld (insy),a
ld a,(killen) ; get length of kill buffer
nomove: push bc
push hl
ex de,hl ; destination to de
ld hl,kilbuf
ld c,a
ld b,0
push bc
ldir
pop de
pop hl
pop bc
ydslp: ld a,(hl)
call outch
inc b
inc c
inc hl
dec e
jr nz,ydslp
ld a,(insy)
inc a
jr nz,..gn3
;
; now redisplay remainder of line, then step back
;
push hl ; save line ptr
push bc
ld e,0 ; character count
ytl1: ld a,c
cp b
jr z,ytl25
inc c
ld a,(hl)
cp ' '
jr nc,ytl2
inc e
ytl2: inc e
call outch
inc hl
jr ytl1
;
ytl25: pop bc
ytl3: call bkspc
dec e
jr nz,ytl3
pop hl
jr ..gn3
;
; abort line
;
cabort: ld bc,0
ld hl,(clsave)
inc hl
jp exit
;
END
ointer
ld e,a
ld d,0 ; de = number of bytes to be freed
ld a,b
sub c ; a has byt