home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
VDE267SC.LBR
/
VDX2.AZM
/
VDX2.ASM
Wrap
Assembly Source File
|
2000-06-30
|
50KB
|
2,963 lines
;*** VDE.ASM (c)1988 E.Meyer
;*** Module 2: functions
;
;
; VDE EDITING FUNCTIONS
;
;Show information
;
Info: CALL MakAlt ;show this first for entertainment
CALL UndrHd
CALL Dspl
DB X,26,0
LD HL,VersID
CALL DspLp
CALL Cmprs ;pack spaces
CALL GpCnt ;count gap size
PUSH BC
LD H,B
LD L,C
LD DE,FreNNN ;show it as "free space"
CALL BCDCon
LD HL,(EndTx)
INC HL
LD DE,(BegTx)
OR A
SBC HL,DE
POP BC
SBC HL,BC ;memory used
LD DE,UsdNNN
CALL BCDCon ;show it as "used"
LD HL,(BegTx)
LD DE,(BefCu)
CALL FSzSbr ;figure actual disk file size
PUSH BC
LD HL,(AftCu)
LD DE,(EndTx)
CALL FSzSbr
POP HL
ADD HL,BC
LD DE,SizNNN ;show it as "file size"
CALL BCDCon
LD A,(Modify)
OR A ;file changed?
LD A,'Y'
JR NZ,Info2
LD A,'N'
Info2: LD (ModQQQ),A
LD HL,InfMsg ;now display the data
CALL DspLp
CALL UnAlt
CALL ESCLp
JP SetAl
;
FSzSbr: LD BC,0 ;count a block
FSzLp: LD A,E ;done?
SUB L
LD A,D
SBC H
RET C
LD A,(HL)
INC HL
INC BC ;count character
CP CR
JR Z,FSz1 ;and (missing) LF?
CP X
JR C,FSzLp ;and (hidden) space?
FSz1: INC BC
JR FSzLp
;
;
; Blank the screen
;
Blank: LD A,(WinFlg) ;window off first (will lose text)
OR A
CALL NZ,Window
LD HL,TInit
CALL CtlStr
CALL EscLp
CALL DoHdr
JP SetAl
;
;
;Move cursor to the beginning of text
;
Top: LD HL,(BegTx)
CALL MoveL ;Move
CALL TopV ;Adjust cursor
CALL LftH
LD HL,1
LD (CurLin),HL
JP SetAl
;
;
;Move cursor to the last character of text
;
Bottom: LD HL,(BefCu) ;for CountL
LD (LastCu),HL
LD HL,(EndTx)
CALL MoveR ;Move
CALL BotV ;Adjust cursor
CALL RitH
CALL CountL
JP SetAl
;
;
;QUICK cursor movements
;
QuikMk: CALL NdCnt ;look for next place marker
JR C,QkMk1
LD HL,(AftCu)
LD A,EOF ;marker
CPIR
JP Z,QikB1 ;found? rest same as ^QB
QkMk1: CALL BgCnt ;not? try from top
JR C,QkMk2
LD HL,(BegTx)
LD A,EOF
CPIR
JP Z,QikB0 ;found? rest same as ^QB
QkMk2: JP Error7 ;not? error.
;
QuikLf: LD E,1 ;move left to start of line
CALL CrLft
RET C
LD A,1
LD (CurCol),A ;(useful for format subroutines)
CALL MoveL
CALL LftH
JP IfScl
;
QuikRt: CALL NdCnt ;move right to end of line
JP C,ColCnt
CALL Fetch
CP CR
JP Z,ColCnt
CALL Right
JR QuikRt
;
QuikUp: LD A,(Vert) ;move up to top of screen
DEC A
RET Z
LD B,A
LD A,(CurCol)
PUSH AF
QUlp: PUSH BC
CALL Up
POP BC
DJNZ QUlp
CALL SetNo
POP AF ;restore col
JP SkQUD
;
QuikDn: LD A,(TxtLns) ;move down to end of screen
LD HL,Vert
SUB (HL)
RET Z
LD B,A
LD A,(CurCol)
PUSH AF
QDlp: PUSH BC
CALL Down
POP BC
DJNZ QDlp
CALL SetNo
POP AF
JP SkQUD
;
ZipTo: LD HL,PageQ ;zip to given page
LD A,(PgLen)
OR A
JR Z,ZipTo0
LD A,(FMode)
CP 'N'
JR NZ,ZipTo1
ZipTo0: LD HL,LineQ ;or line, in N mode
ZipTo1: CALL Prompt
LD BC,1
CALL GetNbr
JP C,Error7
JP Z,Error7
LD A,(FMode)
CP 'N'
JR Z,ZipTo2
LD A,(PgLen) ;(calculate line)
OR A
JR Z,ZipTo2
LD D,0
LD E,A
LD L,D
LD H,D
DEC BC
ZipMul: LD A,B
OR C
JR Z,ZipMF
ADD HL,DE
DEC BC
JR ZipMul
ZipMF: INC HL
LD B,H
LD C,L
ZipTo2: PUSH BC
CALL Top
POP DE ;desired line
LD A,D
OR E
JR Z,ZipXit
DEC DE ;lines to move down
XOR A
OR D
JR Z,ZipLpF
ZipLp: PUSH DE ;do multiples of 256
LD E,0 ;(256)
CALL CrRit
DEC HL
CALL MoveR
POP DE
DEC D
JR NZ,ZipLp
ZipLpF: XOR A
OR E
JR Z,ZipTo3
CALL CrRit ;do remainder
DEC HL
CALL MoveR
ZipTo3: CALL MidV
CALL RitH
CALL CountS
ZipXit: JP SetAl
;
;
;Move cursor up.
;
Up: CALL TestCu ;no delays here
CALL NZ,ShoCu1
LD E,2 ;start of last line
CALL CrLft
RET NZ ;TOF? quit
PUSH HL
CALL EdgeU
CALL DecV
POP HL
CALL MoveL
SkUpDn: LD A,(CurCol) ;where we were
SkQUD: CALL GoCol
RET Z ;exact?
JP IfScl ;may need to scroll
;
;
;Move cursor down.
;
Down: CALL TestCu ;no delays here
CALL NZ,ShoCu1
LD E,1 ;start of next line
CALL CrRit
DEC HL
JR NC,Sk1Dn ;was there one?
RET NZ ;EOF? quit
LD HL,(EndTx)
LD A,(HL) ;Get that last byte
CP CR
RET NZ ;no next line
Sk1Dn: PUSH HL
CALL EdgeD
CALL IncV
POP HL
CALL MoveR
JR SkUpDn
;
;
GoCol: DEC A ;restore cursor to column A
RET Z
LD HL,(HorFlg) ;don't change show status
PUSH HL
PUSH AF
CALL ColCnt ;where are we?
LD IY,CurCol
JR GRCent
GRCLp: CALL NDCnt
JR C,GRCF ;stop at EOF
CALL Fetch
CP CR ;stop at CR
JR Z,GRCF
CP TAB ;tabs are special
JR NZ,GRC1
LD A,(IY)
DEC A
LD HL,TabCnt
OR (HL) ;round up
INC A
LD (IY),A
GRC1: INC (IY) ;Keep CurCol updated
CALL Right
GRCent: POP AF
PUSH AF
CP (IY) ;there yet?
JR NC,GRCLp
GRCF: POP AF
POP HL
LD (HorFlg),HL
INC A
SUB (IY) ;set Z if exact
RET
;
;
;Move cursor one to the left (C=cannot)
;
Left: CALL Space ;Any space left?
RET C
CALL BgCnt ;Are we at front?
RET C
CALL EdgeL
LD HL,(BefCu) ;Look back
LD A,(HL)
BIT 7,(HL) ;Hidden space?
JR Z,Sk1Lt ;No, just move
RES 7,(HL) ;Yes, unhide it
LD A,' '
INC HL
Sk1Lt: DEC HL ;Back up
LD (BefCu),HL
CALL InsrA1 ;store byte ahead
CP TAB ;Was a TAB moved
JR Z,LftTab
CP CR ;Was a CR moved?
JR Z,LftCR
CALL DecH ;no
OR A
RET NZ
JP IfScl ;at left mgn...scroll?
;
LftCR: CALL RitH ;special cases - scrolling
CALL DecV
CALL ColCnt
DEC A
LD HL,View
CP (HL)
CALL NC,HorScl
OR A
RET
LftTab: LD A,(Horiz)
DEC A
CALL Z,HorScl ;need to scroll if at left
CALL LTabH
OR A
RET
;
;
;Move cursor one to the right
;(return C if can't, char passed in A)
;
Right: CALL Space ;Any room left?
RET C
CALL NdCnt ;Already at end?
RET C
CALL EdgeR
CALL Fetch
CP CR
JR NZ,Sk0Rt
PUSH HL
CALL TestCu ;change of line: no delays
CALL NZ,ShoCu1
POP HL
Sk0Rt: LD A,(HL)
BIT 7,A ;Hidden space?
JR Z,Sk1Rt ;No, just move
LD (HL),' ' ;Yes, unhide it
AND 7Fh
DEC HL
Sk1Rt: INC HL ;Bump pointer
LD (AftCu),HL
CALL Insrt1 ;put byte in behind
OR A ;and return it
PUSH AF
CP TAB ;TAB and CR are special
JR Z,RtTab
CP CR
JR Z,RtCR
CALL IncH ;no, just move
POP AF
RET
;
RtCR: CALL IfScl ;may have to scroll
CALL IncV ;adjust
CALL LftH
LD A,1
LD (CurCol),A
POP AF
RET
;
RtTab: LD A,(View)
DEC A
LD HL,TabCnt
SUB (HL)
LD HL,Horiz
SUB (HL)
CALL C,HorScl ;at right, need to scroll
CALL TabH
POP AF
RET
;
;
;Word tab, delete
;
WdMxCh EQU 255 ;max chars to loop
;
WordRt: CALL Fetch ;Word tab right
CP CR ;at EOL? special case
JP Z,Right
CALL IsBlnk ;on break? just find nonbreak
JR Z,WRlpF
LD B,WdMxCh
WRlp: PUSH BC
CALL Right
CALL IsBlnk ;find wordbreak
CALL NZ,IsPunc
POP BC
JR Z,WRlpF
CP CR ;quit at CR
RET Z
DJNZ WRlp
WRlpF: LD B,WdMxCh
WRlp2: PUSH BC
CALL Right
CALL IsBlnk ;then nonbreak
CALL NZ,IsPunc
POP BC
RET NZ
DJNZ WRlp2
RET
;
WordLf: CALL FetchB ;Word tab left
CP CR ;at BOL? Special case
JP Z,Left
LD A,(Vert)
PUSH AF
LD B,WdMxCh
WLlp: PUSH BC
CALL Left
CALL IsPara ;find a nonbreak
CALL NZ,IsPunc
POP BC
JR NZ,WLlpF
CP CR ;quit at CR
JR Z,WLlp2F
DJNZ WLlp
WLlpF: LD B,WdMxCh
WLlp2: PUSH BC
CALL Left
CALL IsPara ;then a break
CALL NZ,IsPunc
POP BC
JR Z,WLlp2F
DJNZ WLlp2
WLlp2F: CALL Fetch
CP CR
CALL Z,LftH ;(avoid silly redisp)
CALL BgCnt
CALL NC,Right ;then back (unless at TOF)
POP AF
DEC A
JP Z,DecVO ;fix line-one bug
RET
;
WordDl: CALL Fetch ;Word Delete
CP CR ;at BOL? special case
JP Z,EChar
CALL IsPara
CALL NZ,IsPunc
JR Z,WDlNB ;on break? delete till nonbreak
CALL IsParB
CALL NZ,IsPunB
PUSH AF
CALL WDlB ;nonbreak? delete till break
POP AF
RET NZ ;BOW? delete till nonbreak too
WDlNB: LD B,WdMxCh
WDlp2: CALL IsPara ;delete till nonbreak
CALL NZ,IsPunc
RET NZ
CP CR ;but quit at CR
RET Z
PUSH BC
CALL EChar
POP BC
DJNZ WDlp2
RET
WDlB: LD B,WdMxCh
WDlp: CALL IsPara ;delete till break
CALL NZ,IsPunc
RET Z
PUSH BC
CALL EChar
POP BC
DJNZ WDlp
RET
;
Join: CALL IsPara ;(this version eats CRs too)
CALL NZ,IsPunc
JR Z,WDlNBx ;on break? delete till nonbreak
CALL IsParB
CALL NZ,IsPunB
PUSH AF
CALL WDlB ;nonbreak? delete till break
POP AF
RET NZ ;BOW? delete till nonbreak too
WDlNBx: LD B,WdMxCh
WDlp2x: CALL IsPara ;delete till nonbreak (including CRs)
CALL NZ,IsPunc
RET NZ
PUSH BC
CALL EChar
POP BC
DJNZ WDlp2x
RET
;
;
;Move cursor ahead one page
;
PageF: CALL SetAl
LD A,(TxtLns)
DEC A
LD E,A ;default scroll
LD HL,Ovlap
SUB (HL)
JR C,PgF1
INC A
LD E,A
PgF1: CALL CrRit ;Point that many CRs down
DEC HL ;Back off one byte
JP C,Bottom
JP NZ,Bottom
LD DE,(BefCu) ;Prepare Count
LD (LastCu),DE
CALL MoveR ;Move cursor gap
CALL CountL
LD A,(CurCol)
JP GoCol ;relocate cursor
;
;
;Move cursor back one page
;
PageB: CALL SetAl
LD A,(TxtLns)
LD E,A
DEC A ;default scroll
LD HL,Ovlap
SUB (HL)
JR C,PgB1
ADD 2
LD E,A
PgB1: CALL CrLft ;Point that many CRs back
JP C,Top
JP NZ,Top
LD DE,(AftCu) ;Prepare Count
LD (LastCu),DE
CALL MoveL ;Move cursor gap
CALL CountR
LD A,(CurCol)
JP GoCol ;relocate cursor
;
;
;Scroll screen 1/4 vertically
;
ShftD: LD A,(TxtLns) ;Down
SRL A
SRL A
INC A
LD B,A
IF VDM
JR LDLp
Scr1LD: LD B,1 ;one-line scroll, VDM
ENDIF
LDLp: PUSH BC
CALL DecVO
JR NZ,LDLpF
CALL Down ;oops, cursr already on top
CALL DecVO
LDLpF: POP BC
DJNZ LDLp
JP SetAl
;
ShftU: LD A,(TxtLns) ;same, up
SRL A
SRL A
INC A
LD B,A
IF VDM
JR LULp
Scr1LU: LD B,1 ;one-line scroll, VDM
ENDIF
LULp: PUSH BC
CALL IncVO
JR NZ,LULpF
CALL Up ;oops, cursr already on bottom
CALL IncVO
LULpF: POP BC
DJNZ LULp
JP SetAl
;
IF NOT VDM
Scr1LD: CALL DecVO ;FAST one-line scrolls
JR NZ,ScLD1
CALL Down ;oops, already on top
CALL DecVO
ScLD1: LD HL,DelL
CALL ScrlUD
LD A,(TxtLns)
LD B,A
JP ShoLn ;re-show last line
;
Scr1LU: LD HL,(CurLin)
LD DE,(Vert)
LD D,0
OR A
SBC HL,DE
RET Z ;oops, nowhere to go
CALL IncVO
JR NZ,ScLU1
CALL Up ;oops, already on bottom
CALL IncVO
ScLU1: LD HL,InsL
CALL ScrlUD
JP ShoLn1
ENDIF
;
;Scroll screen 32 cols horizontally
;
ShftR: LD HL,Horiz ;INcrease screen scroll (right)
LD A,(HL)
SUB 33
RET C
INC A
LD (HL),A
LD HL,NSkip
LD A,(HL)
ADD 32
LD (HL),A
JP SetAl
;
ShftL: LD A,(Horiz) ;DEcrease scroll (left)
ADD 32
LD HL,View
CP (HL)
RET NC
LD (Horiz),A
LD HL,NSkip
LD A,(HL)
SUB 32
RET C
LD (HL),A
JP SetAl
;
;
;Make current line top
;
MakTop: CALL TopV ;gee boss, that was easy, huh?
JP SetAl
;
;
;FIND/REPLACE
;
;Find next occurance of a given string.
;
Find: CALL FndSub
JP C,Error7
CALL ShoLn1
;
RpFind: LD A,(FndStr) ;length
OR A
RET Z ;no string, quit
LD A,(FBackw)
OR A ;backward?
JR NZ,RpF5
CALL NdCnt ;number to scan
JP C,Error4 ;EOF?
LD HL,FndStr
LD A,C
SUB (HL)
LD C,A ;less string length
LD A,B
SBC 0
LD B,A
JP C,Error4
INC BC ;in case last
LD HL,(BefCu)
LD (LastCu),HL ;Mark position
LD HL,(AftCu)
LD A,(ChgFlg) ;was last operation change?
OR A
JR NZ,RpF1
INC HL ;NO, start at next byte
RpF1: DEC BC ;YES, start at this byte
LD A,B
OR C
JP Z,Error4 ;gotta have bytes
LD A,(FUCase)
CP 0C3H ;ucase? (groan)
JR Z,SlowFi
LD A,(FndStr) ;only one char? (groan)
DEC A
JR Z,SlowFi
LD DE,(FndStr+1) ;space in char 1 or 2? (groan)
LD A,' '
CP D
JR Z,SlowFi
CP E
JR Z,SlowFi
JR FastFi
;
RpF5: CALL BgCnt ;backward: number to scan
JP C,Error4 ;EOF?
LD HL,(AftCu)
LD (LastCu),HL ;Mark position
LD A,(ChgStr)
LD HL,ChgFlg ;IF last op was change,
AND (HL) ; back up to start of new string
LD E,A
LD D,0
LD HL,(BefCu) ;else start before cursor
SBC HL,DE
PUSH HL
PUSH BC
POP HL
SBC HL,DE
PUSH HL
POP BC
POP HL
JP Z,Error4 ;gotta have bytes
JR BackFi
;
FastFi: LD A,(FndStr+1) ;find lead char FAST with CPIR
CPIR
JP PO,Error4 ;NOT found
PUSH BC
PUSH HL
LD C,0 ;no hidden spaces involved
CALL FndChk ;rest of string?
POP HL
POP BC
JR NZ,FastFi ;no match, keep going
LD C,0
JP Found
;
SlowFi: LD A,(FndStr+1) ;find lead char the slow way
LD (LdChar+1),A ;(spaces or upcase involved)
LD D,H
LD E,L
ADD HL,BC
EX DE,HL
LD C,0
Lp1Fi: LD (FindSv),BC ;save hidden space status
CALL GetNx
CALL FUCase
LdChar: CP 0 ;<----
JR Z,Lp1Fi1 ;got one
Lp1Fi0: LD A,H
XOR D
JR NZ,Lp1Fi
LD A,L
XOR E
JR NZ,Lp1Fi
JP Error4
Lp1Fi1: PUSH BC
PUSH DE
PUSH HL
CALL FndChk ;rest of string?
POP HL
POP DE
POP BC
JR NZ,Lp1Fi0 ;no, keep trying
LD BC,(FindSv) ;YES, indicate whether lead is hidden
JR Found
;
BackFi: LD A,(FndStr+1) ;find lead char backwards
LD (LdChr2+1),A
PUSH HL
OR A
SBC HL,BC
PUSH HL
POP DE
POP HL
INC HL
INC HL ;adjust for kludge below
LD C,0
Lp1BF: LD A,C
LD (FindSv),A ;clear hidden space status
OR A
JR Z,Lp1BFa
DEC C
LD A,' '
JR Lp1BFb
Lp1BFa: DEC HL ;back up
DEC HL
LD A,(HL)
INC HL ;simulate GetNx in reverse
BIT 7,A
JR Z,Lp1BFb
INC C
Lp1BFb: AND 7Fh
CALL FUCase
LdChr2: CP 0 ;<-----
JR Z,Lp1BF1 ;got one
Lp1BF0: LD A,H
XOR D
JR NZ,Lp1BF
LD A,L
XOR E
JR NZ,Lp1BF
JP Error4
Lp1BF1: PUSH HL
PUSH DE
PUSH BC
CALL FndChk ;rest of string?
POP BC
POP DE
POP HL
JR NZ,Lp1BF0 ;no, keep trying
LD BC,(FindSv) ;YES, indicate whether lead is hidden
JR FoundB
;
FndChk: LD A,(FndStr) ;is (HL) a hit?
DEC A
RET Z ;just one char: already matched
LD B,A
LD DE,FndStr+2 ;start at char2
Lp1FC: CALL GetNx
CALL FUCase
EX DE,HL
CP (HL)
EX DE,HL
JR Z,Sk1FC
LD A,(DE) ;hmm, no match
PUSH HL
LD HL,WildCd ;consider wildcard
CP (HL)
POP HL
RET NZ ;NOPE.
Sk1FC: INC DE ;match, keep on
DJNZ Lp1FC
RET ;YES.
FUCase: JP UCase ;<--- becomes RET
;
;
Found: LD A,C ;(note C=1 if began with hidden space)
DEC HL ;point back to char1
DEC HL ;put cursor BEFORE char1
CALL MoveR
LD HL,(AftCu) ;Hidden space there?
BIT 7,(HL)
JR Z,Found1
OR A ;need to be on it?
JR Z,Found1
LD A,(HL)
AND 7FH ;Yep, unhide it
LD (HL),' '
CALL Insrt1
Found1: CALL MidV ;Center on screen
Chged: CALL RitH ;Adjust cursor
CALL CountL ;Adjust line number
LD HL,ChgFlg
BIT 0,(HL)
JP Z,SetAl ;find? redisplay
LD HL,FndStr
XOR A
ADD (HL)
JR Z,Chgd1
LD C,A ;change: CR involved?
LD B,0
INC HL
LD A,CR
CPIR
JP Z,SetAl ;yes
Chgd1: LD HL,ChgStr
XOR A
ADD (HL)
JP Z,SetCu ;no
LD C,A
LD B,0
INC HL
LD A,CR
CPIR
JP Z,SetAl
JP SetCu
;
FoundB: LD A,C ;(note C=1 if began with hidden space)
DEC HL ;point back before char1
CALL MoveL ;Move to found string
LD HL,(AftCu) ;hidden space there?
BIT 7,(HL)
JR Z,FounB1
OR A ;yes, need to be on it?
JR Z,FounB1
LD A,(HL) ;Yes, unhide it
AND 7Fh
LD (HL),' '
CALL Insrt1
FounB1: CALL MidV ;Center on screen
CALL RitH ;Adjust cursor
CALL CountR ;Adjust line number
JP SetAl
;
FndSub: LD HL,FindQ ;Get Find string
CALL Prompt
CALL GetStr ;Put string in 80
LD DE,FndStr
LD (DE),A
RET Z ;no string
INC DE
XOR A
LD (ChgFlg),A ;find, not change
LD (FBackw),A ;not (yet) backwards
LD A,0C9h ;(RET)
LD (FUCase),A ;not (yet) Uppercase
LD HL,DMA
LD A,(HL)
CP '/'
JR NZ,FndSb2
INC HL
FndSL1: LD A,(HL)
INC HL
OR A
RET Z
CP '/' ;do /options/
JR Z,FndSb2
CALL UCase
CP 'I'
JR Z,FOptI
CP 'B'
JR Z,FOptB
SCF ;error!
RET
FOptI: LD A,0C3h ;(JP) ignore case
LD (FUCase),A
JR FndSL1
FOptB: LD A,0FFh ;backward
LD (FBackw),A
JR FndSL1
FndSb2: LD B,0
FndSL2: LD A,(HL) ;move string in
INC HL
CALL FUCase
OR A
JR Z,FndSLF
LD (DE),A
INC DE
INC B
JR FndSL2
FndSLF: LD A,B ;count
LD (FndStr),A
RET
;
;Change found string [this entry NOT currently in use]
;
;Change: CALL ChgSub ;get string
;
RepChg: LD HL,(BefCu) ;mark position
LD (LastCu),HL
LD A,(FndStr)
OR A
JR Z,RpCh1F ;no string
LD B,A ;count to erase
RpCh1: PUSH BC
CALL EChar
POP BC
JP C,Error7
DJNZ RpCh1
RpCh1F: LD HL,ChgStr ;point to string
LD A,(HL) ;count to replace
OR A
JR Z,RpCh3 ;quit if no new string
LD B,A
RpCh2: INC HL
PUSH BC
PUSH HL
LD A,(HL)
CALL Insrt
POP HL
POP BC
CALL C,Error1
DJNZ RpCh2
RpCh3: JP Chged
;
ChgSub: LD A,0FFH ;say we've done a change
LD (ChgFlg),A
LD HL,ChgQ
CALL Prompt
CALL GetStr ;Put string in 80
PUSH AF
CALL ShoLn1 ;may need this later
POP AF
LD DE,ChgStr
LD (DE),A
RET Z ;do not LDIR with B=0
INC DE
LD C,A
LD B,0
LD HL,DMA
LDIR ;Move string in
RET
;
;Global replace
;
Rplace: LD A,0FFH
LD (YNFlg),A
CALL FndSub
JP C,Error7
LD A,(FndStr)
OR A
RET Z ;no string?
LD A,(MacFlg)
PUSH AF ;(got to do this before Chg input)
CALL ChgSub
POP AF
OR A
CALL NZ,Global ;within Macro: force Global
CALL RepFCh ;do first one
JR C,RplLpQ ;none found?
RplLp: CALL Keybd
CP ESC ;abort?
JR Z,RplLpX
CALL RepFCh
JR NC,RplLp
RplLpX: LD A,(EdErr)
CP 4 ;suppress "not found" error
CALL Z,Error0
RplLpQ: CALL XLoud
JP SetAl
;
;Repeat last find/replace
;
Repeat: LD A,0FFH
LD (YNFlg),A
CALL RepFCh
LD A,(YNFlg)
OR A
JR Z,RplLp
RET
;
RepFCh: CALL RpFind ;[entry from Replace]
LD A,(EdErr) ;return Carry if not found or error
OR A
SCF
RET NZ ;not found
LD A,(ChgFlg)
OR A
RET Z ;find only, all done
CALL ShoAll ;replace, gotta show it
CALL YesNo ;..and ask
JR C,RepFC0
JR Z,RepFC1
LD A,(FBackw) ;NC,NZ = No
OR A
JR NZ,RepFCB
LD A,(FndStr)
CALL GoRtA ;skip ahead
OR A
RET
RepFCB: CALL Left ;(or back)
OR A
RET
RepFC0: RET NZ ;C,NZ means Esc: abort
RepFC1: CALL RepChg ;Z (C or NC) means Yes
LD A,(EdErr)
CP 1 ;error? sat carry
CCF
RET
;
YesNo: LD A,(YNFlg) ;return C=abort, Z=yes
OR A
SCF
RET Z ;"*" mode? Z,C = yes,global
CALL Loud ;MUST see this
YesNo1: LD DE,DspEsc ;entry for hyphenation Y/N
CALL GoTo
CALL MakAlt
LD HL,YNMsg ;say "Y/N/*"
LD B,12
CALL BHLMsg
CALL Cursr
CALL KeyIn ;MUST come from keyboard
PUSH AF
IF VDM
CALL CursrX
ENDIF
LD DE,DspEsc ;clean up
CALL GoTo
LD B,12
CALL BBlank
CALL UnAlt
POP AF
CP ESC ;abort?
JR NZ,YN1
OR A
SCF ;C, NZ = yes
RET
YN1: CP '*'
JR NZ,YN2
Global: CALL XQuiet
XOR A
LD (YNFlg),A ;set global flag
SCF
RET ;Z,C = yes,globally
YN2: AND 5FH
CP 'Y'
RET Z ;Z,NC = yes,once
CP 'N'
JR NZ,YesNo1
OR A
RET ;NZ,NC = no
;
;
;Variable Tabs.
;"VTList" is a list of settings, increasing order, zero fill
;
VTTog: LD HL,VTFlg ;toggle variable on/off
CALL ToggHL
CALL RulFix
VTshow: LD A,(VTFlg) ;requires header display
OR A
LD HL,VTon
JR NZ,VTsho1
LD HL,TogOff
VTsho1: LD DE,DspTab
JP TogSho
;
;
VarTab: CALL ColCnt ;advance to next VT setting
LD B,VTNum
LD HL,VTList
VTlp1: CP (HL) ;find it
JR C,VTb2
INC HL
DJNZ VTlp1
RET ;none, no action.
VTb2: LD A,(HL)
PUSH HL
DEC A
LD HL,View
CP (HL)
CALL NC,HorScl ;may need to scroll
POP HL
LD A,(InsFlg)
OR A ;is insert on?
LD A,(HL) ;column to move to
JP Z,MvCol
JP MvColI ;move by inserting spaces
;
TaBack: CALL ColCnt ;retreat to last tab setting
DEC B
RET Z
LD A,(VTFlg)
OR A
JR Z,BThard
LD C,B
XOR A
LD B,VTNum
LD HL,VTList+VTNum-1
BTlp1: CP (HL) ;skip 0s
JR NZ,BTb1
DEC HL
DJNZ BTlp1
RET ;no tabs at all, no action
BTb1: LD A,C
BTlp2: CP (HL) ;find it
JR NC,BTb2
DEC HL
DJNZ BTlp2
JP QuikLf ;no more left, go to col 1
BTb2: LD A,(HL) ;that's it
JR BTabX
BThard: LD A,(TabCnt) ;back to last multiple
CPL
DEC B
AND B
INC A
BTabX: PUSH AF
CALL QuikLf ;go all the way back
POP AF
JP MvCol ;then go there
;
;
VTSet: LD HL,ColQ ;Set tab(s)
CALL Prompt
CALL GetStr
LD A,(CurCol) ;default is Here
JR Z,VTSt01 ;nothing entered?
LD DE,DMA
LD A,(DE)
CP '@'
JR Z,VTSInt ;interval specified?
CP '#'
JR Z,VTSGrp ;group?
CALL GetNN ;nope, single tab set
JR Z,VTerr
VTSt01: CALL VTStCl
JR C,VTerr
JR VTStX
VTStCl: LD E,A ;[sbr: set VT here]
LD A,(VTList+VTNum-1)
OR A
SCF
RET NZ ;must be room in list
LD BC,VTNum
LD HL,VTList
VTSlp1: LD A,(HL) ;find it
OR A
JR Z,VTSt1
CP E
RET Z ;(quit if already set)
JR NC,VTSt2
INC HL
DEC C
JR NZ,VTSlp1
DEC HL ;last place
VTSt1: LD (HL),E ;add at end
OR A
RET
VTSt2: LD A,E
LD HL,VTList+VTNum-2 ;make room here
LD DE,VTList+VTNum-1
DEC BC
LDDR
LD (DE),A ;put it in
OR A
RET
VTErr: JP Error7
;
VTSInt: EX DE,HL
LD DE,VTList ;"@" interval specified
LD B,VTNum
XOR A
CALL Fill ;clear all existing tabs
EX DE,HL
INC DE
CALL GetNN
LD C,A
INC A ;"@n" means n+1, 2n+1 etc
LD DE,VTList
LD B,VTNum
VTSlp2: LD (DE),A
INC DE
ADD A,C
JR C,VTStX
DJNZ VTSlp2
JR VTStX
VTSGrp: EX DE,HL
LD DE,VTList ;'#' group specified
LD B,VTNum
XOR A
CALL Fill ;clear all existing tabs
EX DE,HL
VTGlp: INC DE
CALL GetNN ;get one from list
OR A
PUSH DE
CALL NZ,VTStCl ;set it?
POP DE
JR C,VTerr
LD A,(DE)
OR A
JR NZ,VTGlp
VTStX: CALL ShoLn1 ;all done
JP RulFix
;
;
VTClr: LD HL,ColQ ;clear a tab
CALL Prompt
LD A,(CurCol) ;default is Here
CALL GetNum
JR C,VTerr
JR Z,VTerr
LD B,VTNum
LD HL,VTList
VTClp1: CP (HL) ;find it
JR Z,VTCl2
INC HL
DJNZ VTClp1
JR VTerr ;wasn't set
VTCl2: LD (HL),0
DEC B
JR Z,VTClX ;was last, all done
LD D,H
LD E,L
INC HL
LD C,B
LD B,0
LDIR ;delete it
XOR A
LD (DE),A ;zero fill
VTClX: CALL ShoLn1
JP RulFix
;
;
; INSERTION FUNCTIONS
;
;Store a ctl-code in text
;
CtlP: LD HL,CPTog ;say "^P-_", get key
CALL Prefix
CALL XCase
CP DEL
JR Z,CtlP1
CP ' ' ;error if not now ctl-char
RET Z ;(space cancels)
JP NC,Error2
CtlP1: LD HL,BlkChr
CP (HL) ;don't allow block char
JP Z,Error2
CP TAB ;tabs are special
JR Z,ITab
CP CR ;so are CRs
JP Z,ICRB1
CP EOF ;place marker always INSERTS
JR NZ,Sk2IC
CALL Insrt
CALL IncH
JP SetRCu
;
;Insert ordinary char (not TAB,CR) left of cursor
;
IChar: CP ' ' ;Main menu entry: no control codes allowed
RET C
Sk2IC: PUSH AF
CALL ChkLM ;Check for left margin
JR NC,Sk2aIC
CALL UpToLM
CALL SetCu
Sk2aIC: POP AF
LD E,A
CP 7FH ;redo line if DEL/ctl
CCF
JR C,Sk3IC
CP ' '
Sk3IC: CALL C,SetRCu
PUSH DE
IF VDM
LD HL,(CPos)
LD (SPos),HL
ENDIF
CALL NC,XPutCh ;just show nice chars
POP DE
PUSH DE
LD A,E
CALL Insrt ;Put byte in
POP DE
RET C ;Full?
PUSH DE
LD A,(Horiz)
LD HL,View
CP (HL)
CALL NC,HorScl ;scroll if at edge
CALL IncH ;Move cursor
CALL ChkIns ;adjust for insert mode
POP DE
LD A,E
CP ' '
RET Z ;if not space,
JP WdWrap ;check wordwrap
;
;Insert a tab
;
TabKey: LD A,(VTFlg)
OR A
JP NZ,VarTab ;maybe variable tabbing
ITab: LD A,TAB
CALL Insrt
RET C
CALL SetCu
CALL ChkIns
LD A,(Horiz)
LD HL,TabCnt
ADD (HL)
LD HL,View
CP (HL)
CALL NC,HorScl ;scroll if needed
JP TabH
;
;Do a carriage return
;
ICR: LD A,(DSFlg)
OR A
CALL NZ,ICR1
ICR1: LD A,(InsFlg)
BIT 7,A ;Is insert flag on?
JR NZ,ICRB1
CALL QuikRt ;noo...
LD A,(FMode)
CP 'N'
JR Z,ICR01
ICR00: CALL FetchB ;<CR> in Document: make HCR
CP ' '
JR NZ,ICR01
CALL Delete
JR ICR00
ICR01: CALL Cursr ;may need to show new HCR
IF VDM
CALL CursrX ;turn cursor off again
ENDIF
CALL NdCnt ;Are we at end?
JR C,ICRB1 ;Yes, add a new line
CALL IfScl ;no, just move cursor
CALL Right
JR ChkAI
ICRB: CALL ICRB1
LD A,(DSFlg)
OR A
RET Z
ISCRB: LD A,' ' ;doublespace? add soft CRLF
CALL Insrt
ICRB1: CALL IfScl
LD A,CR
CALL Insrt ;Put it in
RET C
LD A,(Vert)
LD HL,TxtLns
CP (HL)
CALL Z,ScrlU ;end of screen? scroll
CALL SetDn
CALL IncV ;Move cursor down
CALL LftH ;Move to start of line
JR ChkAI
ICRA: CALL ICRA1
LD A,(DSFlg)
OR A
RET Z
LD A,' ' ;doublespace? add soft CRLF
CALL InsrtA
ICRA1: LD A,CR ;Used as ^N routine only
CALL InsrtA
JP SetDn
;
;
;Check for insert mode
;
ChkIns: LD A,(InsFlg)
OR A ;INSERT on?
JP NZ,SetRCu ;Yes, all done
LD HL,(AftCu) ;No, Look at the character
LD A,CR
CP (HL) ;Is it a CR?
RET Z ;Yes, leave it
LD A,TAB
CP (HL) ;TAB? redo line
CALL Z,SetCu
LD A,(ShoFlg)
PUSH AF
CALL EChar ;overwrite character
POP AF
LD (ShoFlg),A
RET
;
;Check for auto indent mode
;
ChkAI: LD A,(AIFlg) ;AI on?
OR A
RET Z
CALL NdCnt ;adding text at end?
JR C,ChkAII
LD A,(InsFlg) ;insert on?
OR A
JR Z,ChkALp
LD A,(RtMarg) ;If RM set, avoid wierd WW/AI conflict
DEC A
RET NZ
ChkAII: CALL IndPL ;YES, go to previous line
RET C
CALL CntSpc ;get indentation
PUSH AF
CALL IndNL ;back to this line
POP AF
INC A
JP MvCol ;do it
ChkALp: CALL Fetch ;NO, just move to first nonspace
CP ' '
RET NZ
CALL Right
JR ChkALp
;
IndNL: CALL QuikRt ;these are just like RfmNL/PL,
CALL NdCnt ; except they DON'T skip over blank lines
RET C
CALL Right
OR A
RET
IndPL: CALL QuikLf
CALL BgCnt
RET C
CALL Up
OR A
RET
;
;
; DELETION FUNCTIONS
;
;UNdelete a character
;
Undel: CALL GpCnt ;Anything to undelete?
RET C
LD A,0FFh
LD (Modify),A
LD HL,(AftCu)
DEC HL ;here goes
LD (AftCu),HL
LD A,(HL)
CP CR ;was it a CR?
JP Z,SetDn
JP SetRCu
;
UndlLn: CALL GpCnt ;Do a whole line
RET C
LD A,0FFh
LD (Modify),A
LD A,B
OR A ;max 256 chars
JR Z,UdLn1
LD BC,256
UdLn1: LD HL,(AftCu)
DEC HL
DEC HL
LD A,CR
CPDR ;look for CR
RET NZ
INC HL
INC HL ;start of line
LD (AftCu),HL
JP SetDn
;
;
;Erase character to left of cursor (C=error)
;
Delete: CALL Left
RET C ;Fall through to EChar
;
;
;Erase character to right of cursor (C=error)
;
EChar: CALL NdCnt ;Anything to erase?
RET C
LD A,0FFh
LD (Modify),A
CALL SetRCu
LD HL,(AftCu)
BIT 7,(HL) ;Hidden space?
JR Z,Sk1EC
CALL GpShft ;unhide it
LD HL,(AftCu)
LD A,(HL)
LD (HL),' '
AND 7FH
DEC HL
LD (HL),A
RET
Sk1EC: LD A,(HL)
INC HL ;Move up, past character
LD (AftCu),HL ;Store updated value
CP CR
CALL Z,SetDn ;ate a CR?
OR A
RET
;
GpShft: CALL GpCnt ;Shift gap contents left (for Undel sake)
RET C
DEC BC
LD A,B
OR C
SCF
RET Z
LD HL,(BefCu)
INC HL
LD A,B
SUB 08H ;Maximum 2k worth
JR C,GpS1
LD B,08H
ADD H
LD H,A
GpS1: LD D,H
LD E,L
INC HL
LDIR
OR A
RET
GpCR: CALL GpShft ;mark BOL for ^QU
RET C
LD A,CR
LD (DE),A
RET
;
;
;Line erase functions
;
ELine: CALL SetDn ;Erase whole line
LD HL,(AftCu) ;first left end
PUSH HL
CALL QuikLf
POP HL
LD (AftCu),HL
LD E,1 ;now right end
CALL CrRit
JR NC,ELret ;found CR? good
JR NZ,ELret2 ;EOF? return
LD HL,(EndTx) ;Cursor is in last line
INC HL
JR ELret
;
EOLine: LD E,1 ;Erase to EOL
CALL CrRit
JR NC,Sk1EO ;Found CR? good
RET NZ ;EOF? return
LD HL,(EndTx) ;cursor is in last line
LD A,(HL)
CP CR ;Is last byte a CR?
INC HL
JR NZ,Sk2EO ;No
Sk1EO: DEC HL ;Point at trailing CR
Sk2EO: PUSH HL
JR EBLret ;delete to there
;
EBLine: LD HL,(AftCu) ;Erase to BOL
PUSH HL
CALL QuikLf
EBLret: CALL GpCR ;delete to there
POP HL
CALL SetCu
ELret: LD (AftCu),HL
ELret2: LD A,0FFh
LD (Modify),A
RET
;
E2Char: LD HL,CQTTog ;Erase to character
CALL Prefix
CP ESC
RET Z
LD (PrevCh),A
E2CLp: CALL EChar ;always eat first char
CALL NdCnt
RET C
CALL Keybd
CP ESC
RET Z
CALL Fetch
LD HL,PrevCh
CP (HL)
JR Z,E2CLpF
LD (PrvCh2),A
JR E2CLp
E2CLpF: CP CR
RET NZ
LD A,(FMode)
CP 'N'
RET Z
LD HL,PrvCh2 ;CR means HARD CR in Doc modes
LD A,(HL)
CP ' '
RET NZ
LD (HL),CR
JR E2CLp
;
;
; BLOCK FUNCTIONS
;
;MARK Block start and termination
;
Block: CALL UnBlAb ;Remove any markers above
CALL UnBlB1 ;Remove all but last marker below
Blk01: LD A,(BlkChr) ;mark it now
CALL Insrt
CALL IncH
JP SetAl
;
Termin: CALL UnBlA1 ;Remove all but first marker above
CALL UnBlBl ;Remove any markers below
JR Blk01
;
Unmark: CALL UnBlAb ;Remove all block markers
CALL UnBlBl
JP SetAl
;
;Move cursor to block start
;
QikBlk: CALL IsBlk
EX DE,HL
INC HL
BIT 0,A
JP Z,Error7 ;must be marked
BIT 6,A
JR NZ,QikB1
QikB0: CALL MoveL ;before cursor (entries from QuikMk)
JR QikB2
QikB1: DEC HL ;after cursor
CALL MoveR
QikB2: CALL CountS ;Adjust count
CALL RitH ;Adjust cursor
CALL MidV
JP SetAl
;
;Basic query returns:
; A= {bit 7=gap in block; 6=start after gap; 1=block marked; 0=start marked}
; DE,HL= start, end (if marked)
;
IsBlk: LD IX,IsBVal
LD (IX),0 ;result byte
CALL BgCnt
JR C,IsB1
LD A,(BlkChr) ;look before cursor
CPIR
JR NZ,IsB1
SET 0,(IX) ;found start
LD D,H
LD E,L
DEC DE
JP PO,IsB0
CPIR
JR NZ,IsB0
SET 1,(IX) ;found end
DEC HL
IsB5: LD A,(IX) ;exit
RET
IsB0: SET 7,(IX) ;straddle
JR IsB1a
IsB1: SET 6,(IX) ;block after cursor
IsB1a: CALL NdCnt ;now look after cursor
JR C,IsB5
LD HL,(AftCu)
IsB3: LD A,(BlkChr) ;search loop
CPIR
JR NZ,IsB5
BIT 0,(IX)
JR NZ,IsB2
SET 0,(IX) ;found start
LD D,H
LD E,L
DEC DE
JP PO,IsB5
JR IsB3
IsB2: SET 1,(IX) ;found end
DEC HL
JR IsB5
;
;
UnBlA1: CALL BgCnt ;undo all but 1st marker above
RET C
LD A,(BlkChr)
CPIR
JP PE,UnBA01 ;one? leave and look for more
RET ;no more, finished
UnBlAb: CALL BgCnt ;undo all markers above
RET C
UnBA01: LD A,(BlkChr)
CPIR
RET NZ ;none, finished
PUSH BC
PUSH HL
LD D,H
LD E,L
DEC DE
CALL LCnt
JR C,UnBA02
LDIR ;remove it
UnBA02: DEC DE
LD (BefCu),DE
POP HL
DEC HL
POP BC
LD A,B
OR C
JR NZ,UnBA01
RET
;
UnBlB1: CALL NdCnt ;undo all but 1st marker below
RET C
LD HL,(EndTx)
LD A,(BlkChr)
CPDR
JP PE,UnBB01 ;one, leave and continue
RET ;none, finished
UnBlBl: CALL NdCnt ;undo all markers below
RET C
LD HL,(EndTx)
UnBB01: LD A,(BlkChr)
CPDR
RET NZ ;none, finished
PUSH BC
PUSH HL
LD D,H
LD E,L
INC DE
CALL RCnt
JR C,UnBB02
LDDR ;remove it
UnBB02: INC DE
LD (AftCu),DE
POP HL
INC HL
POP BC
LD A,B
OR C
JR NZ,UnBB01
RET
;
;Erase Block
;
EBlock: CALL IsBlk
BIT 1,A ;must be marked
JP Z,Error7
BIT 7,A
JR NZ,EPrt3 ;straddles cursor?
BIT 6,A ;is it after cursor?
JR NZ,EPrt2
LD B,H ;no, before cursor
LD C,L
LD HL,(BefCu)
SBC HL,BC ;bytes to move
PUSH HL
LD H,B
LD L,C
POP BC
JR Z,EPrt1a
INC HL
LDIR
EPrt1a: DEC DE
LD (BefCu),DE
JR EPrtRt
EPrt2: EX DE,HL ;it's after cursor
LD BC,(AftCu)
PUSH HL
SBC HL,BC
LD B,H
LD C,L
POP HL
JR Z,EPrt2a
DEC HL
LDDR
EPrt2a: INC DE
LD (AftCu),DE
JR EPrtRt
EPrt3: DEC DE ;cursor straddles it
LD (BefCu),DE
INC HL
LD (AftCu),HL
EPrtRt: CALL RitH ;Adjust cursor
CALL CountS
LD A,0FFh
LD (Modify),A
JP SetAl
;
;Block Copy
;
Copy: CALL IsBlk
AND 82H ;must be marked, not straddled
CP 2 ;(bit 1 set, 7 clear)
JP NZ,Error7
DEC HL
INC DE
PUSH HL
INC HL
SBC HL,DE ;compute length
LD B,H
LD C,L
POP HL
RET Z ;was empty
LD DE,(AftCu)
DEC DE
CALL CpSafe
JR NC,Copy02 ;okay, go do it
CALL Cmprs ;try to get more room
CALL IsBlk
DEC HL
INC DE
PUSH HL
INC HL
SBC HL,DE ;compute length now
LD B,H
LD C,L
POP HL
LD DE,(AftCu)
DEC DE
CALL CpSafe ;well?
JP C,Error1 ;REALLY won't fit
Copy02: LDDR
INC DE
LD (AftCu),DE
CALL RitH ;Adjust cursor
CALL CountS
LD A,0FFh
LD (Modify),A
JP SetAl
;
CpSafe: PUSH HL ;Set C if BC bigger than gap
PUSH BC
CALL GpCnt
LD H,B
LD L,C
POP BC
SCF ;(just to be safe)
SBC HL,BC
POP HL
RET
;
;Block Move
;
MovBlk: CALL Copy ;first copy
LD A,(EdErr)
OR A
RET NZ
JP EBlock ;then delete
;
;
; DISK FUNCTIONS
;
;View Directory
;
Dir: LD HL,DirQ
CALL Prompt
LD A,3+1 ;ask for Duu
CALL GSEnt
LD A,(FCB) ;defaults
LD B,A
LD A,(FCBU)
LD C,A
JR Z,Dir00
LD DE,DMA
LD A,(DE)
CALL UCase ;new D (?)
CP '0'
JP C,Error7
CP '9'+1
JR C,Dir0
SUB 'A'-1
CP 17
JP NC,Error7
LD B,A
INC DE
Dir0: PUSH BC
CALL GetNN ;new uu
POP BC
JR NC,Dir0a
XOR A
Dir0a: CP 16
JP NC,Error7
LD C,A
Dir00: PUSH BC
LD E,C
LD C,USRN
CALL BDOSep ;set user
POP BC
LD HL,FCBBuf
LD (HL),B ;and drive
INC HL
LD (HL),'?' ;set up *.* FCB
LD DE,FCBBuf+2
LD BC,10+1
LDIR
LD (HL),0
LD BC,19
LDIR
CALL MakAlt
LD DE,010Fh ;position to col 2
LD A,(RulFlg)
OR A
JR Z,Dir1
INC D
Dir1: CALL GoTo
IF NOT VDM
LD A,(View) ;initialize
SUB 14
LD (HPos),A
ENDIF
LD A,(TxtLns) ;lines free on screen
DEC A
LD (DirLns),A
LD A,(View) ;columns free
LD HL,DirCls
LD (HL),A
XOR A
RRD ;cols=view/16
LD C,(HL)
DEC C
PUSH BC
LD DE,FCBBuf ;first file?
LD C,SRCH
CALL BDOS
POP BC
CP 0FFH
JR NZ,Sk1Dir
CALL DsplC
DB 'N','o'+X,'File',CR,0
JP Sk3Dir
;
Lp3Dir: PUSH BC
LD DE,FCBBuf ;next one...
LD C,SRCN
CALL BDOS
POP BC
CP 0FFH
JP Z,DirEnd ;all done?
Sk1Dir: ADD A
ADD A
ADD A
ADD A
ADD A ;desired FCB is at 32*A + DMA
LD E,A
LD D,0
LD HL,DMA
ADD HL,DE
INC HL ;point to filename
EX DE,HL
LD HL,9
ADD HL,DE ;test SYS attribute
BIT 7,(HL)
JR Z,Sk2Dir
LD A,(DirSys) ;yes, include?
OR A
JR Z,Lp3Dir
Sk2Dir: EX DE,HL
PUSH HL
LD B,11
Lp4Dir: LD A,(HL)
AND 7FH ;strip flags
LD (HL),A
INC HL
DJNZ Lp4Dir
LD DE,4
ADD HL,DE
LD (HL),0 ;terminator
DEC HL
LD A,' ' ;separator
LD (HL),A
DEC HL
LD (HL),A
DEC HL
LD (HL),A
DEC HL
LD D,H
LD E,L
DEC HL
LD A,C ;move TYP
LD BC,3
LDDR
EX DE,HL
LD (HL),'.' ;punctuate
POP HL
LD C,A
PUSH BC
CALL DspLp ;SHOW IT
POP BC
DEC C
JR NZ,Lp3Dir ;finish line?
LD HL,DirLns
DEC (HL)
JR Z,DirFul ;out of room?
LD A,CR
CALL DsByt ;okay, new line
LD A,(DirCls)
LD C,A
JR Lp3Dir
;
DirFul: CALL DsplC ;ran out of lines
DB '...',CR,0
JR Sk3Dir
DirEnd: LD A,C ;done, need CR?
LD HL,DirCls
CP (HL)
JR Z,Sk3Dir
LD A,CR
CALL DsByt
Sk3Dir: CALL UnAlt
CALL IfSpLn
LD A,(FCBU)
LD E,A
LD C,USRN ;reset user
CALL BDOSep
CALL SetAl
JP EscLp ;wait for ESC to clear
;
;Load a new file.
;
Load: LD A,(Modify)
OR A
JR Z,LoadY
LD HL,QuitQ ;warn if old file was changed
CALL Prompt
CALL Confrm
JP NZ,ShoLn1
LoadY: JP Restrt ;go do it
;
;Erase a disk file.
;
Era: CALL SavNam ;save old FCB
LD HL,EraQ
CALL NewNam
LD A,(EdErr)
OR A
JR NZ,EraDon
CALL CPM3
LD A,(FCB)
CALL C,RstDrv ;reset drive
LD DE,FCB
LD C,FDEL
CALL BDOS
INC A
CALL Z,Error7
EraDon: CALL GetNam ;restore FCB
JP ShoLn1
;
;
;Read text from disk file to cursor location.
;
Read: CALL SavNam ;save old FCB
LD HL,ReadQ
CALL NewNam
LD A,(EdErr) ;check entry error
OR A
JR NZ,RdDone
;
LoadIt: CALL IOon ;say wait
CALL Cmprs ;need all our room
CALL GpCnt
JR C,Sk1Rd ;No room?
LD HL,(BefCu) ;Start here
CALL MSIn ;Read it in
JR NZ,Sk2Rd ;Worked?
Sk1Rd: CALL Error1 ;no, out of room
JR RdDone
Sk2Rd: JR NC,Sk3Rd ;Okay?
CALL Error3 ;no, I/O error
JR RdDone
Sk3Rd: LD DE,(BefCu) ;Get old BefCu
LD (BefCu),HL ;Set new one
EX DE,HL
INC HL ;Point at first byte loaded
CALL MoveL ;Move the cursor
RdDone: CALL GetNam ;restore FCB
CALL IOoff
LD A,0FFh
LD (Modify),A
JP SetAl
;
;
;Write the whole file out to disk.
;
Save: LD A,(FCB+1) ;must have filename
CP ' '
JR NZ,Save00
CALL ChgNam
JR Save
Save00: LD A,(Modify)
OR A
JR NZ,Save01
LD HL,UnchgQ ;hey, no changes!
CALL Prompt
CALL Confrm
PUSH AF
CALL ShoLn1
POP AF
RET NZ
Save01: CALL IOon ;say wait
LD HL,(AftCu)
LD (LastCu),HL ;save position
LD HL,(BegTx)
CALL MoveL ;go to top of file
CALL NdCnt ;count number of bytes
JR NC,Save02
LD BC,0
Save02: LD HL,(AftCu) ;point at first byte
CALL MSOut ;write it out
JR NC,Save03
CALL Error3
JR Save04
Save03: XOR A
LD (Modify),A ;clean slate
Save04: LD HL,(LastCu)
DEC HL
CALL MoveR ;go back
JP IOoff
;
;
;Write block text to a disk file.
;
Write: CALL SavNam ;save orig FCB
LD HL,WritQ
CALL NewNam
LD A,(EdErr) ;check entry error
OR A
JR NZ,WrXit
CALL IOon ;say wait
LD HL,(AftCu) ;save position
LD (LastCu),HL
LD HL,(BegTx)
CALL MoveL ;go to top of file
CALL IsBlk
BIT 1,A ;must be marked
JR Z,WrOops
INC DE ;point to it
SBC HL,DE ;size of block
EX DE,HL
LD B,D
LD C,E
CALL MSOut
JR NC,WrDone
WrOops: CALL Error7
WrDone: LD HL,(LastCu)
DEC HL
CALL MoveR ;go back
CALL IOoff
WrXit: CALL GetNam ;restore orig FCB
JP ShoLn1
;
;
SavNam: LD HL,FCB ;Preserve main filename
LD DE,FCBBuf
LD BC,12
LDIR
LD A,(FCBU) ;And User, W/A, FilFlg
LD (DE),A
INC DE
LD A,(FMode)
LD (DE),A
INC DE
LD A,(FilFlg)
LD (DE),A
RET
GetNam: LD HL,FCBBuf ;And restore them
LD DE,FCB
LD BC,12
LDIR
LD A,(HL)
LD (FCBU),A
LD E,A
INC HL
LD A,(HL)
LD (FMode),A
INC HL
LD A,(HL)
LD (FilFlg),A
LD C,USRN
JP BDOSep
;
;
;Accept a new file name to be used for disk i/o.
;
ChgNam: CALL SavNam
LD HL,NameQ
CALL NewNam
LD A,(EdErr)
OR A
CALL NZ,GetNam ;bad? restore
CALL DfltM ;may have changed modes
CALL DoHdr
LD A,0FFh
LD (Modify),A
JP ShoLn1
;
NewNam: CALL Prompt ;subroutine entry
LD A,20+1
CALL GSEnt ;Ask for input
JP Z,Error7 ;Error if no input
LD B,A
PUSH BC
LD HL,DMA ;uppercase it
NNUlp: LD A,(HL)
CALL UCase
LD (HL),A
INC HL
DJNZ NNUlp
POP BC ;restore length
LD HL,DMA
LD A,(HL)
CP '[' ;watch for mode only
JR Z,NNMod
LD A,B
CALL Parse ;parse DU:FN.T [O
JP C,Error7 ;check bad entry
XOR A
LD (FilFlg),A ;kill fileflg
RET
NNMod: INC HL
LD A,(HL) ;do mode only
CP 'W'
JR Z,NNMdOK
CP 'A'
JR Z,NNMdOK
CP 'N'
JP NZ,Error7
NNMdOK: LD (FMode),A
RET
;
DfltM: LD HL,0101H
LD (LMSav),HL ;margins set
LD A,(FMode) ;doc or nondoc mode?
CP 'N'
JR Z,Dflt2
LD A,0FFH ;document mode:
LD (VTFlg),A ;varitabs on
LD A,(HCDflt)
LD (HCRFlg),A ;HCR display?
LD A,(RtMarg)
DEC A
JR NZ,DfltX
LD HL,(DfltLM) ;from NONdoc: reset margins
LD (LfMarg),HL
JR DfltX
Dflt2: LD HL,0101H ;NONdocument mode
LD (LfMarg),HL
XOR A
LD (VTFlg),A ;varitabs off
LD (HCRFlg),A ;HCR display off
DfltX: JP RulFix
;
;
;Toggle case of character at cursor
;
UpLow: CALL Fetch ;also points to byte with (HL)
AND 5FH ;strip off both hidden spc and case
CP 'A'
JR C,UpLo1 ;leave alone if not letter
CP 'Z'+1
JR NC,UpLo1
BIT 5,(HL) ;toggle case
RES 5,(HL)
JR NZ,UpLo1 ;was lower, now up
SET 5,(HL) ;was upper, now low
LD A,0FFh
LD (Modify),A
UpLo1: CALL Right ;move right for next(?)
JP SetRCu
;
;
;Set page length
;
PgSet: LD HL,PgLnQ
CALL Prompt
LD A,(FormL) ;default value
CALL GetNum
JP C,Error7
LD (PgLen),A
CALL DoHdr
JP ShoLn1
;
;
;VARIOUS TOGGLES
;
;Simple on/off toggles
;
HCRTog: CALL SetAl ;HCR display
LD HL,HCRFlg
ToggHL: LD A,(HL)
CPL
LD (HL),A
RET
;
;These require header display
;
HypTog: LD HL,HypFlg ;hyphenation
CALL ToggHL
HYshow: LD HL,HYon
LD A,(FMode)
CP 'N' ;irrelevant in N mode
JR Z,HYsho0
LD A,(HypFlg)
OR A
JR NZ,HYsho1
HYsho0: LD HL,TogOff
HYsho1: LD DE,DspHyp
JP TogSho
;
IToggl: LD HL,InsFlg ;INSERT
CALL ToggHL
ITshow: LD A,(InsFlg)
OR A
LD HL,INSon
JR NZ,ITsho1
LD HL,TogOff
ITsho1: LD DE,DspIns
JP TogSho
;
DblTog: LD HL,DSFlg ;double spacing
CALL ToggHL
DSshow: LD A,(DSFlg)
OR A
LD HL,DSon
JR NZ,DSsho1
LD HL,TogOff
DSsho1: LD DE,DspSpc
JP TogSho
;
AITog: LD HL,AIFlg ;auto indentation
CALL ToggHL
AIshow: LD A,(AIFlg)
OR A
LD HL,AIon
JR NZ,AIsho1
LD HL,TogOff
AIsho1: LD DE,DspInd
JP TogSho
;
;
;TEXT FORMAT functions
;
SetRM: LD A,(FMode) ;Set right margin
CP 'N' ;(must be Document mode)
JR Z,RMerr
LD A,(RMSav) ;okay, do it
DEC A
CALL NZ,RelM ;(undo Margin Release)
LD HL,ColQ
CALL Prompt
LD A,(CurCol) ;default: cursor column
CALL GetNum
JR C,RMerr
JR Z,RMerr
LD C,A
LD A,(LfMarg)
CP C
JR C,SRM1 ;inside LM?
LD A,1
LD (LfMarg),A ;if so, reset LM
SRM1: LD A,C
LD (RtMarg),A
CALL RulFix
JP ShoLn1
RMerr: JP Error7
;
SetLM: LD A,(FMode) ;Same for left
CP 'N'
JR Z,RMerr
LD A,(RMSav)
DEC A
CALL NZ,RelM ;(undo Margin Release)
LD HL,ColQ
CALL Prompt
LD A,(CurCol)
CALL GetNum
JR C,RMerr
JR Z,RMerr
LD HL,RtMarg
CP (HL)
JR NC,RMerr ;gotta be within RM
LD (LfMarg),A
CALL RulFix
JP ShoLn1
;
RelM: CALL RelLM ;release both margins (Toggle)
LD HL,RtMarg
LD DE,RMSav
CALL RelSb
CALL MRshow
JP RulFix
MRshow: LD A,(RMSav) ;requires header display
DEC A
LD HL,MRon
JR NZ,MRsho1
LD HL,TogOff
MRsho1: LD DE,DspMrg
JP TogSho
;
;
RelLM: LD HL,LfMarg ;SBR: release left only
LD DE,LMSav
RelSb: LD A,(HL) ;common subroutine
CP 1
JR Z,Rel1
LD (DE),A ;note: if RMSav>1, margins released
LD (HL),1
RET
Rel1: LD A,(DE)
LD (HL),A
LD A,1
LD (DE),A
RET
;
;Check the right margin
;
ChkRM: LD A,(CurCol) ;be sure this is up to date
LD B,A
LD A,(RtMarg)
INC A
LD C,A
SUB B ;set C if over
RET NC
CALL IgnCtl ;yes, ignore ctlchars
LD A,C ;try arithmetic once again
ADD E
SUB B
RET ;now C set if really over
;
IgnCtl: CALL Fetch ;count ctlchars to be ignored
LD E,0 ;(up to present cursor)
LD HL,(BefCu)
CP CR
JR NZ,IgnC1
IgnCLp: LD A,(HL) ;count em
DEC HL
CP CR ;quit at BOL
RET Z
IgnC1: CP TAB ;tabs don't count
JR Z,IgnCLp
CP 20H
JR NC,IgnCLp
INC E ;others do
JR IgnCLp
;
;Check left margin, space over if needed
;
ChkLM: LD A,(LfMarg)
LD B,A
LD A,(CurCol)
SUB B ;be sure this is uptodate
RET ;ret Z if at, C if over
;
UpToLM: LD A,(LfMarg) ;git on over to the LM column
;
MvCol: PUSH AF ;move to col A saving any existing text
CALL GoCol
POP AF
MvColI: LD HL,CurCol ;move to col A inserting spaces
SUB (HL)
RET C ;we're past already
RET Z ;we're there
LD B,A
CALL SetCu ;this is going to hurt
MvClp: PUSH BC ;insert B spaces
LD A,' '
CALL Insrt
POP BC
RET C ;quit if out of space
CALL IncH
DJNZ MvClp
RET
;
DoLM: LD A,(LfMarg) ;create whole left margin
DEC A
RET Z
LD B,A
JR MvClp
;
;Handle former margin for reformat
;
CntSpc: CALL QuikLf ;count lead spaces on line
XOR A
CSpLp: PUSH AF
CALL Fetch
CP ' '
JR NZ,CSpLpF
CALL Right
POP AF
INC A
JR CSpLp
CSpLpF: CALL QuikLf ;back to start
POP AF
RET
;
EatSpc: OR A ;eat up to A lead spaces on line
RET Z
ESpLp: PUSH AF
CALL Fetch
CP ' '
JR NZ,ESpLpF
CALL EChar
POP AF
DEC A
JR NZ,ESpLp
RET
ESpLpF: POP AF
RET
;
;
;Update CurCol and return it in A and B
;(NOTE: slow. When possible, LDA CurCol.)
;
ColCnt: CALL WhatC
LD (CurCol),A
RET
;
WhatC: CALL FetchB ;col 1 is spcl case
CP CR
LD A,1
LD B,A
RET Z
LD E,1
CALL CrLft ;start of line
LD BC,0
;
CCLp: CALL GetNx ;get a char
CP TAB
JR NZ,CC1
LD A,B ;tabs are special
PUSH HL
LD HL,TabCnt
OR (HL) ;round up
POP HL
LD B,A
CC1: INC B ;count char
LD A,B
CP 254
JR Z,CC2 ;too long? return column 255 forever
XOR A
CP C
JR NZ,CCLp ;get hidden space?
PUSH BC
CALL LCnt ;compare HL to BefCu
POP BC
JR NC,CCLp ;get another, if more exist
CC2: INC B
LD A,B ;that is curcol.
RET
;
;
;Do wordwrap if needed
;
WdWrap: LD A,(RtMarg) ;WW off if RM=1
CP 1
RET Z
LD IY,CurCol
INC (IY) ;count the char you just put in
CALL ChkRM
RET NC
LD B,0 ;past margin...
WWLp: INC B ;count moves
PUSH BC
CALL Left
DEC (IY)
POP BC
CALL FetchB
CP CR ;oh no Uncle Bill
JP Z,Error9
CP '-' ;hyphenation
JR NZ,WW1
LD A,(HypFlg)
OR A
JR Z,WW1
CALL Fetch
CP ' '
JR Z,WW1a
INC B
PUSH BC
LD A,' ' ;tuck in a space if there isn't one
CALL Insrt
JR WW2
WW1: CALL Fetch
CP ' '
JR NZ,WWLp
WW1a: PUSH BC
CALL Right ;leave it if there is
INC (IY)
WW2: CALL ChkLM
JR Z,WWerr
JR C,WWerr
CALL ICRB ;break line
CALL DoLM
POP BC
LD A,B
DEC A ;one spc gone
JP GoRtA
WWerr: POP BC
JP Error9
;
GoRtA: OR A ;Go right A chars - used by wordwrap etc
RET Z
PUSH AF
CALL Right
POP AF
DEC A
JR GoRtA
;
;Reform a paragraph
;
Reform: LD A,(RtMarg) ;is RM set?
DEC A
RET Z
CALL QuikLf
CALL NdCnt
JP C,RfmE10
CALL Fetch ;empty line?
CP CR
JP Z,Down
CALL XQuiet
CALL RfmNL ;figure out indentation
JR C,RfmBg
CALL CntSpc
PUSH AF
CALL RfmPL
POP AF
CALL EatSpc ;remove spaces acc. to NEXT line indent
CALL DoLM ;and add current margin
RfmBg: CALL Keybd
CP ESC ;check for abort
JP Z,RfmEnd
CALL ColCnt ;only once per line (slow)
LD IY,CurCol
;
RfmLp: CALL NdCnt
JP C,RfmE10 ;check for EOF
CALL Fetch
CP CR ;and EOL
JP Z,Rfm7
CP TAB ;tabs are special
JR NZ,Rfm3
LD A,(IY)
DEC A
LD HL,TabCnt
OR (HL) ;round up
INC A
LD (IY),A
Rfm3: INC (IY) ;Keep CurCol updated
CALL Right
CALL ChkRM
JR NC,RfmLp
;
Rfm4: CALL Fetch ;just the right length?
CP CR
JR Z,Rfm7
CALL Left ;oops, too long.
CALL FetchB
CP CR
JP Z,RfmErr
CALL Fetch
CP '-' ;hyphenation
JR NZ,Rfm4b
LD A,(HypFlg)
OR A
JR Z,Rfm4b
CALL Right
LD A,' '
CALL Insrt
JR Rfm4c
Rfm4b: CALL IsBlnk ;break after blank
JR NZ,Rfm4
CALL Right
Rfm4c: CALL ColCnt
CALL ChkLM ;watch out for left mgn
JP Z,RfmErr
JP C,RfmErr
CALL ICRB
Rfm5: CALL Fetch ;avoid spurious para
CP CR
JR Z,Rfm6a ;(stop after CR)
CP ' '
JR NZ,Rfm6b
CALL EChar
JR Rfm5
Rfm6a: CALL EChar
JP RfmBg
Rfm6b: CALL DoLM
JP RfmBg
;
Rfm7: CALL FetchB ;is the CR soft or hard?
CP ' '
JR NZ,Rfm9 ;hard, quit
CALL Left ;soft, delete any other spaces
Rfm7a: CALL FetchB
CP ' '
JR NZ,Rfm7b
CALL Delete
JR Rfm7a
Rfm7b: CP '-' ;unhyphenate?
JR Z,Rfm20
Rfm8: CALL Right ;and now the CR itself
CALL EChar
CALL RfmSD ;and any soft CR following
LD A,255
CALL EatSpc ;and any leading spaces
CALL Fetch
CP CR ;hit bald CR?
JR NZ,Rfm8a
CALL Delete ;yep, kill space and quit
JR Rfm9
Rfm8a: CALL Left
CALL Left
CALL IsEndS ;(extra spc for punc)
JR NZ,Rfm8b
CALL Right
LD A,' '
CALL Insrt
Rfm8b: CALL QuikLf
JP RfmBg
Rfm9: CALL Right ;hard CR (check following soft?)
CALL RfmSD ;delete, if there
LD A,(DSFlg)
OR A
CALL NZ,ISCRB ;may need to separate paras
RfmEnd: CALL XLoud
JP SetAl
RfmErr: CALL XLoud
JP Error9
RfmE10: CALL XLoud
JP Eror10
;
Rfm20: LD A,(HypFlg) ;unhyphenation
OR A
JR Z,Rfm8 ;not allowed, continue
Rfm21: CALL Loud
CALL ShoAll
CALL YesNo1
PUSH AF
CALL XQuiet
POP AF
JR NC,Rfm22
JR Z,Rfm21 ;C,Z means "*": unacceptable
JR Rfm8 ;C,NZ means ESC: don't join at all
Rfm22: CALL Z,Delete ;kill hyphen if it was "Yes"
CALL Join ;join lines (whether "Yes or No")
JR Rfm8b
;
RfmNL: CALL QuikRt ;go to next line of text
CALL NdCnt
JR NC,RfmNL0
CALL QuikLf ;oops, none
SCF
RET
RfmNL0: CALL Right
CALL Fetch ;(may be blank)
CP CR
JR NZ,RfmNL1 ;bald CR next? also give up
CALL Up
SCF
RET
RfmNL1: CP ' '
JR Z,RfmNL2
CALL QuikLf ;no, fine, we're here
OR A
RET
RfmNL2: CALL Right
CALL Fetch
CP CR
JR NZ,RfmNL1 ;just spaces and CR? doublespacing,
CALL Right ; go on to next line
JR RfmNL1
RfmPL: CALL QuikLf ;return to previous line of text
RfmPL0: CALL Left
CALL FetchB ;(may be blank)
CP CR
JP Z,RfmPLx ;yes, take next
CP ' '
JR Z,RfmPL0
JP QuikLf ;no, fine
RfmPLx: CALL Left
JP QuikLf
;
RfmSD: CALL Fetch ;delete a soft CR if present
CP ' '
RET NZ
CALL Right
CALL Fetch
PUSH AF
CALL Left
POP AF
CP CR
RET NZ
CALL EChar
JP EChar
;
;
;Center or flush a line
;
Center: LD E,1FH ;(RRA) if Center
CP 'F'-40H
JR NZ,Ctr0
LD E,0C9H ;(RET) if Flush
Ctr0: LD A,E
LD (Flush),A
LD A,(RtMarg)
CP 1
RET Z ;not if no margin
CALL QuikLf ;start of line
CtrL1: CALL Fetch
CP CR
JR Z,CtrXit ;end? done
CALL IsBlnk
JR NZ,CtrL1F
CALL EChar ;delete spaces
JP C,Error9
JR CtrL1
CtrL1F: CALL QuikRt ;end of line
CtrL2: CALL Left
CALL IsBlnk
JR NZ,CtrL2F
CALL EChar ;delete spaces
JR CtrL2
CtrL2F: CALL ColCnt ;where are we?
CALL IgnCtl ;ignore ctlchars
LD HL,CurCol
LD A,(LfMarg)
DEC A
LD B,A
LD A,(RtMarg)
ADD E ;(ctlchars)
SUB B
SUB (HL)
JP C,Error9 ;error
CALL Flush
JR Z,CtrXit
PUSH AF
CALL QuikLf ;start again
CALL DoLM
POP BC
CtrL3: PUSH BC ;insert spaces to center
LD A,' '
CALL Insrt
POP BC
DJNZ CtrL3
CtrXit: CALL QuikLf
CALL ShoCu
CALL QuikRt ;to next line(?)
JP Right
;
Flush: RRA ;<--- goes to RET if Flush
AND 7FH ;take half the difference for Center
RET
;
;
;Fetch character at (or before) cursor
;
Fetch: LD HL,(AftCu)
LD A,(HL)
AND 7FH ;ignore any hidden space
RET
FetchB: LD HL,(BefCu)
LD A,(HL)
BIT 7,A
RET Z ;ordinary byte
LD A,' '
RET ;hidden space
;
;Tests on char at cursor (use only A,HL)
;
IsBlnk: LD HL,BlkTbl ;point to tbl
JR IsTest
IsPara: LD HL,ParTbl
JR IsTest
IsParB: LD HL,ParTbl
JR IsTstB
IsPunc: LD HL,PunTbl
JR IsTest
IsPunB: LD HL,PunTbl
Jr IsTstB
IsEndS: LD HL,EndTbl
;
IsTest: PUSH HL
CALL Fetch
POP HL
JR IsTLp
IsTstB: PUSH HL
CALL FetchB
POP HL
IsTLp: BIT 7,(HL)
JR NZ,IsTst1 ;at end of tbl?
CP (HL)
RET Z ;Z set if match
INC HL
JR IsTLp
IsTst1: OR A ;clear Z if none
RET ;ret char in A
;
PunTbl: DB ',;:-' ;fall thru...
EndTbl: DB '.?!',0FFh ;end with 0FFh
ParTbl: DB CR ;fall thru...
BadTbl: DB 0,EOF ;characters not "part" of file text
BadLen EQU $-BadTbl ;(<--BlkChr patches in here)
BlkTbl: DB ' ',TAB,0FFh ;end with 0FFh
;
;
;END of Module 2