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
/
VDX1.AZM
/
VDX1.ASM
Wrap
Assembly Source File
|
2000-06-30
|
46KB
|
2,510 lines
;*** VDE.ASM - Video Display Editor
;*** Universal Version - (c)1988 Eric Meyer
;*** Module 1: patch areas, core code
; -------------------
; VDE,VDE-2 - 9-12/84 - Enhanced VDO, added functions
; VDE-OS,OX - 7/85-1/86 - Small additions and fixes
; VDE-PX - 7-9/85 - Epson Geneva terminal version
; VDE 1.2-3 - 9/85-1/86 - Generic terminal version
; VDE/M 2.0 - 4/86 - Generic memory map version; CP/M+ support; additions
; 2.1 - 6/86 - New Keys 0-9; window; undo; directory; new pagination,
; compression, block marker, scroll; etc.
; 2.2 - 8/86 - WS-like commands; left mrgn, hyphenation; macros
; 2.3 - 9/86 - VINSTALL; Print options; word fns; real ^QA; RstDrv
; 2.4 - 1/87 - vidRAM/window redone; "W" mode; ^OZ,^QP; block print
; 2.5 - 3/87 - User#s; "N" mode; ^OS, ^OV/+/-; new block fns; hard-CRs
; 2.6 - 7/87 - Allow blank filename; ^U abort; new toggles; ruler;
; ^O<u>; AltBit fixes; works w/o curpos; key buffer; faster
; scrolling; case insensitive searches; no fake "VIDRAM"
; 2.61 - 8/87 - Bug fixes (incl FastFi), improved hyphenation
; 2.62 - 11/87 - ^JKL synonyms; ^W prefix; ^OH; several small fixes
; 2.63 - 1/88 - ^KV; WS style ^W/^Z; chgs to ^OP, ^OI/N, word fns
; 2.64 - 3/88 - ^OQ,^QT,^QI; ^KD; ^QA fixes; dbl spc; top margin;
; backward find; ShoRCu
; 2.65 - 4/88 - ^OI/N args; Esc-TAB; ^OA; menu removal; minor fixes
; 2.66 - 6/24/88 - Printer margins; Minor fixes. LAST RELEASE!
; 2.67b - 10/14/88 - Minor fixes
; -------------------
;
ORG 0100H
JP Start ;Entry and exit vectors
Boot: JP 0
;
;Following VINSTALL data MUST be at 0106-0112H
;
DB 02H+(X AND VDM),66H ;Version compatibility
DW UsrPat
DB UPatL
DW MnuSt
DW KMnuSt
DW OMnuSt
DW QMnuSt
;
VersID: ;0113H: version message (28 chars, used in menu)
IF VDM
; [----5----10---15---20---25--]
DB ' VDE-M 2.67b(c)1988 E.Meyer ',0
ELSE
DB ' VDE 2.67b (c)1988 E.Meyer ',0
ENDIF
;
;
;USER PATCHABLE VALUES
;
ORG 0130H
BAKFlg: DB 0 ;0130H - create BAK files (y/n)
DFMode: DB 'A' ;default file mode W/A/N
FDflt1: DB 'ASMN' ;1st default override
FDflt2: DB 'C N' ;2nd
InsFlg: DB 0 ;default insert on (y/n)
RulFlg: DB 0 ;default ruler on (y/n)
HCDflt: DB 0FFh ;default HCR disp on (y/n)
HypFlg: DB 0FFH ;enable hyphenation (y/n)
DfltLM: DB 1 ;left margin column (1=OFF)
DfltRM: DB 78 ;right margin column (1=OFF)
Ovlap: DB 2 ;scroll overlap (0=none)
DirSys: DB 0 ;include SYS files (y/n)
FixDsk: DB 'P@' ;fixed drives
Ring: DB 0 ;errors ring bell (y/n)
Help: DB 0 ;use help menus (y/n)
AltHdr: DB 0FFH ;use alt video in header (y/n)
NoHdrF: DB 0 ;suppress header (y/n)
IF VDM
MHz: DB 80H ;clock speed (40h=4MHz)
Timer: DB 01H ;horiz scroll delay (01...FF)
ELSE
MHz: DB 50H
Timer: DB 40H
ENDIF
TabCnt: DB 8-1 ;hard tab cols -1 (1/3/7/15)
VTList: DB 6,15,35,55,0,0,0,0 ;variable tab columns (8)
VTNum EQU $-VTList
WildCd: DB '_' ;wildcard character
BlkChr: DB 00H ;block character (^@)
TogTbl: DB 02h,14h,13h,19h ;toggles ^B,^T[^D],^S,^Y
NTgTbl: DB 11h,17h,05h,12h ;switches ^Q,^W,^E,^R (last 015C)
;
;INSTALLATION
;
IF VDM ;Memory Mapped installation
ORG 0160H
DB 'Osborne Exec ' ;ID
ORG 0170H
View: DB 80 ;viewable columns (max 128)
Extra: DB 48 ;empty cols in logical line
Lines: DB 24 ;viewable lines (min 8)
UsrKys: DB 0FFh ;DEL key
DB 0BH,0AH,0CH,0FFH ;arrows up,down,right,left
ORG 0180H
TInit: DB 1, 1AH,0,0,0,0,0,0 ;terminal init, 7 bytes
TUInit: DB 1, 1AH,0,0,0,0,0,0 ;terminal uninit
ORG 0190H
CuOff: DB 3, ESC,'.0',0,0,0 ;cursor hide, 6 bytes
CuOn: DB 3, ESC,'.2',0,0,0 ;cursor unhide
VidRAM: DW 0C000H ;Video RAM address
VidIN: PUSH AF ;Switch Video IN, 16 bytes
LD A,41H
OUT 0,A
POP AF
RET
ORG 01B0H
VidOUT: PUSH AF ;Switch Video OUT
LD A,01H
OUT 0,A
POP AF
RET
ELSE ;Generic Installation
ORG 0160H
DB 'Unidos Osb4 Emul' ;ID
ORG 0170H
View: DB 80 ;viewable columns (max 128)
AuWrap: DB 0FFh ;does autowrap occur
Lines: DB 24 ;lines
UsrKys: DB 0FFh ;DEL key
DB 0BH,0AH,0CH,0FFH ;arrows up,down,right,left
ORG 0179H
ClL: DB 2, ESC,'T',0,0,0,0 ;clear to end of line, 6 bytes
TInit: DB 1, 1AH,0,0,0,0,0,0 ;terminal init, 7 bytes
TUInit: DB 1, 1AH,0,0,0,0,0,0 ;terminal uninit
AltOn: DB 2, ESC,'j',0,0,0,0 ;alt video on, 6 bytes
AltOff: DB 2, ESC,'k',0,0,0,0 ;alt video off
AltBit: DB 0 ;high bit gives alt video?
Filter: DB 7FH ;highest ASCII to send to screen
PosMod: DB 'S' ;curpos mode (Std/Rev/ANSI/None)
PCu: DB ESC,'=',20h,20h ;position cursor to (0,0)
PosDly: DB 0 ;delay after curpos (00-FF)
InsL: DB 2, ESC,'E',0,0,0,0 ;insert line [1], 6 bytes
DelL: DB 2, ESC,'R',0,0,0,0 ;delete line [1], 6 bytes
OddDel: DB 0 ;ins/del line specific?
ENDIF
;
ORG 01C0H ;Printer codes
DB 'Alps ALQ 200 ' ;ID
ORG 01D0H
UseLF: DB 0FFh ;use LF after CR in print?
FormL: DB 56 ;form length (0=no pag)
PTMarg: DB 0 ;top margin skip
DotPO: DB 0 ;left margin skip
PInit: DB 19, 18H,ESC,'!',1 ;printer init, 19 bytes
DB ESC,'x0',ESC,'r0',ESC,'%0',ESC,'l',8,ESC,'Q`'
ORG 01E8H ;printer uninit, 7 bytes
PUInit: DB 6, ESC,'x0',ESC,'!',01H
ORG 01F0H
PCodes: DB 2, ESC,'E',0,0,0,0,0 ;^B toggle on
DB 2, ESC,'F',0,0,0,0,0 ;...and off
DB 3, ESC,'S0',0,0,0,0 ;^T [^D] toggle on
DB 2, ESC,'T',0,0,0,0,0 ;...and off
DB 3, ESC,'-1',0,0,0,0 ;^S toggle on
DB 3, ESC,'-0',0,0,0,0 ;...and off
DB 2, ESC,'4',0,0,0,0,0 ;^Y toggle on
DB 2, ESC,'5',0,0,0,0,0 ;...and off
UCodes: DB 1, 0FH,0,0,0,0,0,0 ;sw 1 (^Q)
DB 3, ESC,'w1',0,0,0,0 ;sw 2 (^W)
DB 3, ESC,'W1',0,0,0,0 ;sw 3 (^E)
DB 6, ESC,'w0',ESC,'!',1,0 ;sw 4 (^R)
;
ORG 0250H
UsrPat: ;0250-027FH - User Patch Area
;(Can extend back into UCodes section if fewer switches used)
;
ORG 0280H ;0280-047FH - Macro keys
UPatL EQU $-UsrPat
Keys: DS 2 ;free count (VDE does this)
K0: DB K1-K0-1, 8EH,90H,13H,0FH,06H ;key 0: horiz. bar
DB 05H,16H,10H,13H,16H,CR
K1: DB K2-K1-1, 8EH,90H,02H,'Eric Meyer' ;1: personal address
DB 10H,02H,0FH,03H,ESC,'+9'
K2: DB K3-K2-1, 8EH,90H,02H,'APTERYX SOFTWARE' ;2: business
DB 10H,02H,0FH,03H,ESC,'+9'
K3: DB K4-K3-1, 90H,9AH,ESC,'1',11H,13H,18H ;3: soften para
DB ESC,'= 2',ESC,'=',CR,'2',13H
DB 16H,' ',16H,04H,ESC,'!1'
DB ESC,'2',11H,10H,7FH
K4: DB K5-K4-1, 8FH,8CH,'7',CR,0FH,12H,'70',CR ;4: quote margins
K5: DB K6-K5-1, 8FH,8CH,'1',CR,0FH,12H,'78',CR ;5: text margins
K6: DB 0 ;null keys 6-7
K7: DB 0
K8: DB K9-K8-1, 8EH,X+'C','ompuServe [74415,1305]' ;8: phone/CIS
DB 0FH,06H,05H,'Phone (405)329-5777',CR
K9: DB KT-K9-1, 8EH,X+'4','01 12th Ave SE, #139' ;9: address/phone
DB 0FH,03H,0EH,'Norman, OK 73071',0FH,03H
DB ESC,'+0'
KT:
;
;
;----- EXECUTION BEGINS HERE -------
;
ORG 0480H
;
Start: SUB A ;check for Z80
RET PE
LD SP,Stack
LD HL,Data ;zero out data area
LD DE,Data+1
LD BC,DataLn-1
LD (HL),0
LDIR
LD C,CPMV
CALL BDOSep
LD (CPM3+1),A ;CP/M version
CALL CPM3
LD C,ERRM ;Error mode to Return?
LD E,0FFh
CALL NC,BDOSep
LD C,GDRV ;save logged drive
CALL BDOSep
LD (CurDsk),A
INC A
LD (FCB),A
LD C,USRN ;and user
LD E,0FFH
CALL BDOSep
LD (CurUsr),A
LD (FCBU),A
IF VDM
LD D,0 ;video RAM anatomy:
LD HL,View ;variable Width,Empty
LD E,(HL)
LD (Width),DE ;Width=View
INC HL
LD E,(HL)
LD (Empty),DE ;Empty=Extra
ENDIF
;LD DE,Lines ;initialize variables
;LD A,(DE)
;LD (OrigLn),A
;LD HL,RulFlg
;ADD (HL) ;(flag is -1 if on)
;LD (DE),A
LD A,(Lines)
LD (PhysLn),A
CALL AdjLns
LD A,(FormL)
LD (PgLen),A
LD HL,(DfltLM)
LD (LfMarg),HL
LD A,(BlkChr)
LD (BadTbl),A
LD A,(UseLF)
CPL
OR LF
LD (LFChr),A
LD HL,MacStr
DEC (HL) ;makes a FF terminator
;
LD HL,DMA
LD A,(HL)
INC HL
CALL Parse ;parse command line
;
CALL VerKey ;verify keys
LD HL,TInit
CALL CtlStr ;Clear and home cursor
IF VDM
LD HL,CuOff
CALL CtlStr ;remove real cursor
ENDIF
JR Edit ;start editing.
;
;Clear it all out and start over.
;
Restrt: LD HL,LoadQ
CALL NewNam
LD A,(EdErr) ;bad name?
OR A
JR NZ,BadLd
;
;Start editing a File
;
Edit: CALL IniRAM ;initialize memory
CALL DfltM ;adjust defaults
CALL DoHdr ;show header
CALL Top ;Start at TOF
CALL Error0 ;No errors
LD A,(FCB+1)
CP ' ' ;Filename blank?
JR Z,Edit1
CALL SavNam ;save it for LoadIt kludge
CALL LoadIt ;Get input file
LD A,(EdErr)
CP 1 ;is it too big?
JR NZ,Edit1
BadLd: CALL DoErr ;Too big, or bad name
CALL BlkFCB ;(Other error means new file)
JR Edit
Edit1: LD A,(MSIFlg) ;set up BAKflag
LD HL,BAKFlg
AND (HL)
LD (FilFlg),A
XOR A
LD (Modify),A
;
Reset: LD SP,Stack ;recover from ^U prompt abort
CALL ShoLn1
;
;
;MAIN LOOP: SHOW TEXT, GET KEY
;
Ready: CALL Orient ;Get bearings
CALL ShoTx ; then show text as needed
CALL Cursr ;position cursor
CALL TRptKy ;Get input
PUSH AF
IF VDM
CALL CursrX ;remove cursor
ENDIF
CALL Error0 ;Clear error indicator
CALL SetNo ;default NO redisp
POP AF
CALL AdjKey ;translate arrows/DEL
;
DoKey: CALL Case ;try to match control code?
DB MnuLn/3
DW IChar ;Default : Insert character
MnuSt EQU $
DB 0 ;(internal use: null key)
DW CKCan
DB 80H ;DEL
DW Delete
DB 81H ;Up arrow
DW Up
DB 82H ;Down
DW Down
DB 83H ;Right
DW Right
DB 84H ;Left
DW Left
DB ESC
DW Escape
DB '^'-40H
DW UpLow
DB '\'-40H
DW Repeat ;Synonym for ^L
DB 'A'-40H
DW WordLf
DB 'B'-40H
DW Reform
DB 'C'-40H
DW PageF
DB 'F'-40H
DW WordRt
DB 'G'-40H
DW EChar
DB 'I'-40H
DW TabKey
DB 'J'-40H
DW DoMnu
DB 'K'-40H
DW CKKey
DB 'L'-40H
DW Repeat
DB 'M'-40H
DW ICR
DB 'N'-40H
DW ICRA
DB 'O'-40H
DW Onscrn
DB 'P'-40H
DW CtlP
DB 'Q'-40H
DW Quick
DB 'R'-40H
DW PageB
DB 'T'-40H
DW WordDl
DB 'U'-40H
DW Undel
DB 'V'-40H
DW IToggl
DB 'W'-40H
DW Scr1LU
DB 'Y'-40H
DW Eline
DB 'Z'-40H
DW Scr1LD
MnuLn EQU $-MnuSt
;
Sk1Ed: LD A,(EdErr) ;Check for error, repeat main loop
OR A
CALL NZ,DoErr
JP Ready
;
;Block commands: ^K toggle is on
;
CKKey: LD HL,CKTog
CALL Prefix
CKSyn: CALL XCase ;Entry for ESC synonyms
CALL Case
DB KMnuLn/3
DW Error2 ;complain if unknown
KMnuSt EQU $
DB 'B'-40h
DW Block
DB 'C'-40h
DW Copy
DB 'D'-40h
DW Done
DB 'E'-40h
DW Era
DB 'F'-40h
DW Dir
DB 'H'-40h
DW DoMnu
DB 'I'-40h
DW Info
DB 'K'-40h
DW Termin
DB 'L'-40h
DW Load
DB 'N'-40h
DW ChgNam
DB 'P'-40h
DW Print
DB 'Q'-40h
DW Quit
DB 'R'-40h
DW Read
DB 'S'-40h
DW Save
DB 'U'-40h
DW Unmark
DB 'V'-40h
DW MovBlk
DB 'W'-40h
DW Write
DB 'X'-40h
DW Exit
DB 'Y'-40h
DW EBlock
DB ESC
DW CKCan
DB ' '
DW CKCan
KMnuLn EQU $-KMnuSt
CKCan: RET
;
;ESC commands: ESC toggle is on.
;
Escape: LD HL,ESCTog
CALL Prefix
CALL AdjKey
CALL UCase
CP '0'
JR C,Esc01 ;macro Keys: special case
CP '9'+1
JP C,UseKey
Esc01: CALL Case
DB EMnuLn/3
DW CKSyn ;default: ^K synonym
EMnuSt EQU $
DB 81H ;Up arrow
DW ShftU
DB 82H ;Down
DW ShftD
DB 83H ;Right
DW ShftR
DB 84H ;Left
DW ShftL
DB '[' ;ANSI cursor sequences
DW ANSIcu
DB TAB
DW TaBack
DB 'M'
DW DoMac
DB '#'
DW MacKey
DB '!' ;macro prog stmts
DW MacJmp
DB '='
DW MacTst
DB '~'
DW MacTsX
DB '+'
DW ChainK
DB ';'
DW Wait
EMnuLn EQU $-EMnuSt
RET
;
;Onscreen commands. ^O toggle is on.
;
Onscrn: LD HL,COTog
CALL Prefix
CALL XCase ;force to ctl
CALL AdjKUp ;adjust UP ARROW ONLY
CALL Case ;What function?
DB OMnuLn/3
DW Error2 ;complain if unknown
OMnuSt EQU $
DB 81H ;up
DW MakTop
DB 'A'-40h
DW AITog
DB 'C'-40h
DW Center
DB 'D'-40h
DW HCRTog
DB 'F'-40h
DW Center ;same fn as 'C'
DB 'H'-40h
DW HypTog
DB 'I'-40h
DW VTSet
DB 'L'-40h
DW SetLM
DB 'N'-40h
DW VTClr
DB 'P'-40h
DW PgSet
DB 'Q'-40h
DW NoHdr
DB 'R'-40h
DW SetRM
DB 'S'-40h
DW DblTog
DB 'T'-40h
DW Ruler
DB 'V'-40h
DW VTTog
DB 'W'-40h
DW Window
DB 'X'-40h
DW RelM
DB 'Z'-40h
DW Blank
DB ESC
DW COCan
DB ' '
DW COCan
OMnuLn EQU $-OMnuSt
COCan: RET
;
;Quick commands. ^Q toggle is on.
;
Quick: LD HL,CQTog
CALL Prefix
CALL XCase
CALL AdjKey ;translate arrow/DEL
CALL Case ;What function?
DB QMnuLn/3
DW Error2 ;complain if unknown
QMnuSt EQU $
DB 80H ;DEL
DW EBLine
DB 81H ;Up arrow
DW QuikUp
DB 82H ;Down
DW QuikDn
DB 83H ;Right
DW QuikRt
DB 84H ;Left
DW QuikLf
DB 'A'-40h
DW Rplace
DB 'B'-40h
DW QikBlk
DB 'C'-40h
DW Bottom
DB 'F'-40h
DW Find
DB 'I'-40h
DW ZipTo
DB 'P'-40h
DW QuikMk
DB 'R'-40h
DW Top
DB 'T'-40h
DW E2Char
DB 'U'-40h
DW UndlLn
DB 'Y'-40h
DW EOLine
DB ESC
DW CQCan
DB ' '
DW CQCan
QMnuLn EQU $-QMnuSt
CQCan: RET
;
;
;
Prefix: PUSH HL ;show prefix, get suffix
LD DE,DspEsc
CALL GoTo
CALL MakAlt
POP HL
LD B,3
CALL BHLMsg
;LD B,9
LD B,1
CALL BBlank
LD DE,DspEsQ ;position cursor
CALL GoTo
IF VDM
CALL SCursr
ENDIF
CALL RptKey ;get suffix
PUSH AF
LD A,(NoHdrF)
OR A
JR NZ,PrefNH
LD DE,DspEsc
CALL GoTo
LD B,4 ;clean up
CALL BBlank
CALL UnAlt
POP AF
RET
PrefNH: CALL UnAlt ;(if no header)
CALL ShoLn1
LD A,(RulFlg)
OR A
CALL NZ,RulFix
POP AF
RET
;
;
;Return to CP/M ... With or without saving
;
Exit: CALL Save ;Save the file
LD A,(EdErr) ;Was it ok?
OR A
RET NZ ;No, do not quit
JR QuitY
;
Done: CALL Save ;Save, and load new
LD A,(EdErr)
OR A
RET NZ
JP Restrt
;
Quit: LD A,(Modify) ;Quit to CP/M
OR A
JR Z,QuitY
LD HL,QuitQ
CALL Prompt
CALL Confrm ;warn if file changed...
JP NZ,ShoLn1
QuitY: LD HL,TUInit ;Clear screen
CALL CtlStr
IF VDM
LD HL,CuOn ;Cursor back on
CALL CtlStr
ENDIF
LD A,(CurDsk) ;restore logged disk
LD E,A
LD C,SELD
CALL BDOS
LD A,(CurUsr) ;and user
LD E,A
LD C,USRN
CALL BDOSep
JP Boot ;restart
;
;Error handler
;
DoErr: CALL Loud ;Show error message, wait for ESC
CALL SetNo
XOR A ;kill any running macro
LD (MacFlg),A
LD A,(EdErr)
CP 10
JP NC,SetAl ;error 10 does NOT show
LD A,(Ring)
OR A
LD E,Bel
CALL NZ,CONOut
CALL MakAlt
CALL UpLft
CALL Dspl
DB X,31,'[[','['+X,0
LD A,(EdErr)
ADD A ;Double the code
LD L,A
LD H,0
LD DE,ErrTab
ADD HL,DE
LD E,(HL) ;Get msg addr from table
INC HL
LD D,(HL)
EX DE,HL
CALL DspLp ;show it
CALL DsplC
DB ' ]]]',CR,0
CALL UnAlt
CALL EscLp
LD A,(EdErr)
CP 1
JR Z,DoErr2
CP 9
JP C,ShoLn1 ;(errors 2-8 need no redisp)
DoErr2: JP SetAl
EscLp: CALL RptKey ;await ESC from console
CP ESC
RET Z
CP ' '
JR NZ,EscLp
RET
;
Error0: LD A,0 ;clear error (don't change flags)
JR ErrSet
Error1: LD A,1 ;error set fns
JR ErrSet
Error2: LD A,2
JR ErrSet
Error3: LD A,3
JR ErrSet
Error4: LD A,4 ;5,6 currently not used
JR ErrSet
Error7: LD A,7
JR ErrSet
Error8: LD A,8
JR ErrSet
Error9: LD A,9
JR ErrSet
Eror10: LD A,10
ErrSet: LD (EdErr),A
RET
;
;
;INPUT ROUTINES
;
KeyIn: LD HL,(Timer) ;Get key, regardless
LD H,0
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
KyIn1: PUSH HL
CALL KyStat
POP HL
DEC HL
JR NZ,Keybd ;read key if got one
LD A,(HorFlg)
LD E,A
LD A,(KeyFlg)
OR E
OR H
OR L ;allow redisp for horizontal scroll?
JR NZ,KyIn1
CPL
LD (HorFlg),A ;yep (just once)
IF VDM
CALL CursrX
ENDIF
CALL ShoAll
CALL Cursr
JR KyIn1
;
Keybd: CALL KyStat ;Get key, or 0 if none
RET Z
LD HL,ConBuf
DEC (HL) ;uncount it
INC HL
LD A,(HL) ;here it is
LD D,H
LD E,L
INC HL
LD BC,ConBufL-1
LDIR ;remove it
AND 7FH ;strip parity
RET
;
KyStat: CALL CONSt ;Console status with buffering
JR Z,ConChk ;all quiet
LD C,A ;got key
LD HL,ConBuf
INC (HL) ;ok, count it
LD E,(HL)
LD D,0
ADD HL,DE ;point there
LD (HL),C ;put it in
LD A,E
CP ConBufL ;buffer full?
JR C,ConChk
ConBsy: LD A,0C9H ;(RET)
LD (Plug),A ;plug up the console until buffer empty
ConChk: LD A,(ConBuf) ;check buffer (FAST)
OR A
RET NZ
XOR A ;buffer empty, unplug console
LD (Plug),A
RET
;
CONSt: XOR A
Plug: NOP ;<--- RET plugs up console
LD E,0FFH ;console status/input
LD C,UCON
CALL BDOSep
OR A ;test for null
RET
;
;
Confrm: CALL RptKey ;get a Y/N answer
CALL UCase
CP 'Y' ;return Z if confirmed
RET Z
CP 'N'
JR Z,CnfNo
CP ESC ;allow this too
JR NZ,Confrm
CnfNo: OR A
RET
;
;Translate four arrow keys and BS,DEL
;
AdjKey: CP 'H'-40h ;First handle ^H (special case)
JR NZ,AdjK0
LD C,80h
LD HL,UsrKys
CP (HL) ;Is it installed as DEL?
JR Z,AKret
LD C,84h ;no, then it's Left arrow
CP A
JR AKret
AdjK0: LD B,5 ;Not ^H, try the rest
JR AdjK1
AdjKUp: LD B,2 ;only do (DEL and) UP arrow
AdjK1: LD HL,UsrKys
LD DE,WSKys
LD C,7FH ;encode 80h=DEL, 81h=up, etc.
AKlp: INC C
CP (HL)
JR Z,AKret
EX DE,HL
INC DE
CP (HL)
JR Z,AKret
INC HL
DJNZ AKlp
CP C
LD C,A ;NO match: return NZ, char in A and C
AKret: LD B,A ;MATCH: return Z, code in A, char in C
LD A,C
LD C,B
RET
WSKys: DB DEL,'E'-40H,'X'-40H,'D'-40H,'S'-40H
;
;
ANSIcu: CALL RptKey ;Handle ANSI cursor keys ESC-[...
SUB 'A'
JP Z,Up
DEC A
JP Z,Down
DEC A
JP Z,Right
DEC A
JP Z,Left
JP Error2
;
;Get string input
;
GetStr: LD A,LinLen+1 ;string length +1
GSEnt: LD (GSlen+1),A ;(entry for GetNum and NewNam)
LD HL,DMA ;*** MUST be 0080h ***
Lp1GS: LD A,L
SUB 80H ;length
GSlen: CP 0 ;<---- max length pastes in here
JR NC,GSBS ;full?
PUSH HL
IF VDM
CALL SCursr ;make a cursor
ENDIF
CALL RptKey ;Get next input
IF VDM
PUSH AF
CALL SCursr ;remove cursor
POP AF
ENDIF
CALL AdjKey ;translate key
POP HL
CP 80H ;corrections? DEL,
JR Z,GSBS
CP 84H ;left
JR Z,GSBS
CP CR ;CR ends
JR Z,GSCR
CP 'U'-40H ;^U aborts operation
JP Z,Reset
CP 'P'-40H ;^P for ctlcode
JR Z,GSctl
LD A,C ;restore orig char
CP 'X'-40H ;wipeout
JR Z,GSwipe
;
Sk1GS: LD (HL),A ;Store byte
INC HL ;Move along
CP 20H
PUSH HL
JR NC,Sk2GS
ADD 40H ;ctls are hili letters
PUSH AF
CALL AltY
POP AF
CALL PutChA
CALL UnAltY
JR Sk3GS
Sk2GS: CALL PutChA ;show byte
Sk3GS: POP HL
JR Lp1GS
;
GSBS: CALL GSBSsb
JR Lp1GS
GSwipe: CALL GSBSsb
JR NZ,GSwipe
JR Lp1GS
GSBSsb: LD A,080h ;Are we at start
CP L
RET Z ;return Z if so
DEC HL ;back up pointer
LD E,BS ;wipe out char
CALL PutCh
LD E,' '
CALL PutCh
LD E,BS
CALL PutCh
OR 1 ;clear flags
RET
;
GSCR: LD (HL),0 ;terminator
LD A,L
SUB 080H ;Compute input length (Z=zero)
RET ;HL points past end of string
;
GSctl: PUSH HL
CALL RptKey
CALL XCase
POP HL
JP Sk1GS
;
;Get numeric input (0-65535 decimal), return C if bad
;
GetNbr: PUSH BC ;BC = default if no input
LD A,5+1
CALL GSEnt ;get up to 3 digits
POP DE
JR NZ,GNyes
LD B,D
LD C,E
LD A,B ;no entry, use default
OR C
RET
GNyes: LD DE,DMA ;fall thru to GetNNN
;
GetNNN: PUSH HL ;gets decimal # pointed by DE
LD H,D
LD L,E
LD B,0
GNL: LD A,(HL)
CP '0'
JR C,GotN ;terminated by any nondigit.
CP '9'+1
JR NC,GotN
INC HL
INC B
LD A,B
CP 5+1
JR NC,GNErr ;5 digits max.
JR GNL
GotN: LD A,B ;okay, do them
LD BC,0
OR A ;digits?
JR Z,GNErr
CP 2
JR Z,Got2
JR C,Got1
CP 4
JR Z,Got4
JR C,Got3
CP 5
JR NZ,GNErr
Got5: LD HL,10000
CALL GNNdig
JR C,GNErr
Got4: LD HL,1000
CALL GNNdig
JR C,GNErr
Got3: LD HL,100
CALL GNNdig
JR C,GNErr
Got2: LD HL,10
CALL GNNdig
JR C,GNErr
Got1: LD HL,1
CALL GNNdig
JR C,GNErr
POP HL
LD A,B
OR C
RET
GNErr: POP HL
SCF ;error
RET
;
GNNdig: LD A,(DE) ;do a digit: HL=power of 10
INC DE
GNNLp: CP '0'
RET Z
DEC A
PUSH HL
ADD HL,BC
LD B,H
LD C,L
POP HL
RET C ;overflow
JR GNNLp
;
;Versions of above for 0...255 only: GetNum, GetNN take # in A
;
GetNum: LD C,A
LD B,0
CALL GetNbr
JR GetNN1
GetNN: CALL GetNNN
GetNN1: RET C
XOR A
OR B
JR NZ,GetNNX
OR C ;result in A, OK
RET
GetNNX: SCF ;oops, too big
RET
;
;
;Convert 16-bit number in HL to a one to five
;digit decimal number in the area pointed to by DE
;
BCDCon: LD IX,P10Tab ;Point at table
PUSH DE ;Save output pointer
BCDlp1: LD B,(IX+1)
LD C,(IX)
LD A,C ;low byte
CP 1 ;Clear carry flag
JR Z,BCDend
SBC HL,BC ;Subtract from input
JR NC,BCDok ;Got one in range
ADD HL,BC ;Restore it
INC IX
INC IX
JR BCDlp1 ;Try next one
;
BCDok: LD A,'1'
LD (DE),A ;Set initial digit
BCDlp2: SBC HL,BC ;Subtract again
JR C,BCDsk1 ;Went negative
EX DE,HL
INC (HL) ;Increment digit
EX DE,HL
JR BCDlp2
;
BCDsk1: ADD HL,BC ;Restore it
INC DE ;Bump output
INC IX
INC IX
LD C,(IX)
LD B,(IX+1)
LD A,C
CP 1 ;Is this last entry
JR Z,BCDend
LD A,'0'
LD (DE),A
JR BCDlp2
;
BCDend: LD A,L
OR '0'
LD (DE),A
INC DE
EX DE,HL
POP BC
SBC HL,BC ;Number filled
LD A,5 ; needed
SUB L ; to do
RET Z
ADD HL,BC ;Restore pointer
BCDlp3: LD (HL),' ' ;Clear field
INC HL
DEC A
JR NZ,BCDlp3
RET
;
P10Tab: DW 10000,1000,100,10,1
;
;
;
;PRINT text from memory
;
Print: LD HL,PgLen ;set defaults
XOR A
CP (HL)
JR NZ,Pr00
INC A ;bit 0 set if no pagn
Pr00: LD (POByt),A
XOR A
LD (HdrLen),A
LD (POff),A
CPL
LD (PNum),A
LD A,1
LD (Copies),A
LD (PBeg),A
LD A,(DotPO)
LD (PrLMrg),A
LD A,(PTMarg)
LD (PrTMrg),A
LD HL,PrtQ ;options?
CALL Prompt
CALL GetStr ;get string into 80
LD DE,DMA ;point to option string
PrOlp: LD A,(DE)
INC DE
LD HL,POByt ;set up bit flags
LD BC,PrOlp
PUSH BC ;(return)
CALL UCase
CP ' ' ;eat spaces
RET Z
CP 'B'
JR Z,POBlk
CP 'D'
JR Z,PODblS
CP 'P'
JR Z,POPau
CP 'L'
JR Z,POLMrg
CP 'T'
JR Z,POTMrg
CP '*'
JR Z,POCpy
CP '^'
JR Z,POCtl
CP '@'
JR Z,POBeg
CP '#'
JR Z,PONum
CP '='
JR Z,POPgS
CP '"'
JP Z,POHdrT
POP BC ;kill return
OR A
JP Z,PORdy ;quit at null
JP Error7 ;unexpected character
;
POCpy: CALL GetNN ;"*" sets copy count
JP C,POBad
LD (Copies),A
RET
POLMrg: CALL GetNN ;"Lnn" sets left margin
JP C,POBad
LD (PrLMrg),A
RET
POTMrg: CALL GetNN ;"Tnn" sets top margin
JR C,POBad
LD (PrTMrg),A
RET
POPau: SET 4,(HL) ;bit 4 is for "P"
RET
PODblS: SET 3,(HL) ;bit 3 is for "D"
RET
POCtl: SET 2,(HL) ;bit 2 is for "^"
RET
POBlk: LD A,(HL)
AND 0C2H ;bits 1,6,7 must be clear
JR NZ,POBad
LD A,(HL)
AND 04H ;preserve bit 2
OR 21H ;set 5 (BLOCK), 0; clear 1,6,7
LD (HL),A
RET
POBeg: BIT 0,(HL) ;must be paginating
JR NZ,POBad
CALL GetNN ;"@" page beginning
JR C,POBad
OR A
JR Z,POBad
LD (PBeg),A
SET 6,(HL) ;bit 6 is for "@" (suppresses output)
SET 7,(HL) ;so is bit 7 (multicopy)
INC A
NEG ;255-@ is most # can be
LD B,A
LD A,(PNum)
CP B
RET C ;okay, less
LD A,B
LD (PNum),A
RET
PONum: BIT 0,(HL) ;must be paginating
JR NZ,POBad
CALL GetNN ;"#" page count
JR C,POBad
OR A
JR Z,POBad
LD B,A
LD A,(PBeg)
ADD B ;@ + # cannot exceed 255
JR C,POBad
LD A,B
LD (PNum),A
RET
POPgS: BIT 0,(HL) ;must be paginating
JR NZ,POBad
CALL GetNN ;"=" starting pagination
JR C,POBad
OR A
JR Z,POBad
LD (POff),A ;offset beginning page
RET
POHdrT: BIT 0,(HL) ;must be paginating
JR NZ,POBad
SET 1,(HL) ;bit 1 requests header
LD (HdrPtr),DE ;point to header text
LD B,50 ;and figure its length
POHlp: LD A,(DE)
INC DE
CP '"'
JR Z,POHlpF
DJNZ POHlp
JR POBad ;too long
POHlpF: LD A,50
SUB B ;length
LD (HdrLen),A
RET
POBad: POP HL ;eat return
JP Error7
;
PORdy: CALL IOon ;say Wait
LD HL,PInit ;init string?
LD B,(HL)
INC HL
CALL LSTStr
LD HL,(AftCu)
LD (LastCu),HL ;save position
LD HL,(BegTx)
CALL MoveL ;move to top of file
LD A,(POff)
OR A
JR NZ,PORdy0
LD A,(PBeg)
PORdy0: LD HL,PBeg
SUB (HL) ;adjust starting page offset
LD (POff),A
LD HL,POByt
BIT 5,(HL)
JR Z,PORdy1
CALL IsBlk ;block print requested
BIT 1,A ; must be marked
JP Z,PrOops
INC DE
PUSH HL
SBC HL,DE
POP HL
RET Z ;block empty
DEC HL
EX DE,HL
JR PORdy2
PORdy1: CALL NdCnt ;print whole file
JP C,PrDone ;file empty
LD HL,(AftCu)
LD DE,(EndTx)
PORdy2: LD (StPrt),HL
LD (EndPr),DE
;
RePrt: LD HL,POByt ;[reprint reentry]
BIT 7,(HL)
JR Z,PRP0
SET 6,(HL) ;remember if "@" was used
PRP0: XOR A
LD (PageN),A
INC A
LD (IgnFlg),A ;TOF is start of line (DotChk)
LD A,(PgLen) ;start first page
LD B,A
OR A
CALL NZ,PgBrk
JR C,Sk4Pr
LD HL,(StPrt) ;Point at first one
LD C,0 ;Initialize GetNx
Lp1Pr: CALL GetNx ;Get a character
CALL DotChk ;(maybe ignore dot command lines)
CP CR
JR NZ,Sk2Pr
CALL PrOut ;It's a CR
PUSH BC
PUSH HL
CALL Keybd
CP ESC ;Abort request?
POP HL
POP BC
JR Z,Sk1Pr
LD A,(POByt)
BIT 3,A ;doublespacing? do extra CR(LFCR)LF
JR Z,Sk0Pr
CALL PLF
LD A,CR
CALL PrOut
LD A,B ;count it (if paginating)
OR A
JR Z,Sk0Pr
DEC B
JR Z,Sk01Pr
Sk0Pr: LD A,B
OR A ;Not paginating? B is and stays 0
LD A,(LFChr) ;Add usual line feed
JR Z,Sk2Pr
DJNZ Sk2Pr
Sk01Pr: CALL PgBrk ;time for NEW PAGE
JR C,Sk4Pr ;done?
JR Sk2aPr
Sk1Pr: LD A,1 ;abort
LD (Copies),A
JR Sk3Pr
Sk2Pr: CALL ChekC ;Check for masking
CALL PrOut ;Output char
XOR A
CP C ;Hidden space waiting?
JR NZ,Lp1Pr
Sk2aPr: LD DE,(EndPr) ;At end?
LD A,E
SUB L
LD A,D
SBC H
JR NC,Lp1Pr ;Loop if more to go
Sk3Pr: LD A,CR
CALL PrOut ;last CRLF for some matrix printers
LD A,(LFChr)
LD C,A
LD A,(PgLen)
OR A ;Finish page?
JR Z,Sk3aPr
LD C,FF
Sk3aPr: LD A,C
CALL PrOut
Sk4Pr: LD HL,PCodes ;undo toggles if on
LD DE,16
LD B,4
Lp2Pr: BIT 7,(HL)
JR Z,Lp2PrF
RES 7,(HL)
PUSH BC
PUSH DE
PUSH HL
LD DE,8
ADD HL,DE
LD B,(HL)
INC HL
CALL LSTStr
POP HL
POP DE
POP BC
Lp2PrF: ADD HL,DE
DJNZ Lp2Pr
LD HL,Copies ;more copies?
DEC (HL)
JP NZ,RePrt
LD HL,PUInit ;uninit string?
LD B,(HL)
INC HL
CALL LSTStr
JR PrDone
PrOops: CALL Error7
PrDone: LD HL,(LastCu) ;all finished
DEC HL
CALL MoveR ;go back to position
CALL IOoff
JP ShoLn1
;
PgBrk: PUSH BC ;call this for new page (returns C for EOP)
PUSH HL
LD A,(PageN)
OR A
LD A,FF ;start new sheet IF not 1
CALL NZ,PrOut
LD A,(POByt)
BIT 4,A ;pause requested?
JR Z,NP00
CALL IOoff ;do it
LD HL,RdyQ
CALL Prefix
CP ESC
JP Z,NPquit
CALL IOon
NP00: LD HL,PageN
INC (HL)
JP Z,NPquit ;255 page limit.
LD C,(HL) ;check "#" limit?
LD A,(PBeg)
LD E,A
LD A,(PNum) ;Pnum+Pbeg-1 = Lastpage#
DEC A
ADD E
JP C,NPquit ;255 page limit
CP C
JP C,NPquit ;"#" pages printed... quit.
LD A,(PBeg)
LD C,A
LD A,(PageN)
CP C
LD HL,POByt
JR C,NP10 ;are we "@" yet?
RES 6,(HL) ;yes (start) printing
CALL DoPOf ;begin with margin offset
NP10: LD A,(PrTMrg)
OR A
JR Z,NP20
LD B,A
NP11Lp: CALL PCRLF ;top margin?
DJNZ NP11Lp
NP20: LD HL,POByt
BIT 1,(HL)
JR Z,NPnoh ;want header?
LD A,(HdrLen)
ADD 6
LD B,A
LD A,(RtMarg) ;column for page no.
SUB B
JR NC,NPlp
LD A,70 ;default if margin unusable
SUB B
NPlp: PUSH AF ;space over to right justify header
LD A,' '
CALL PrOut
POP AF
DEC A
JR NZ,NPlp
LD HL,(HdrPtr) ;put out header
LD A,(HdrLen)
LD B,A
CALL POStr
LD A,' '
CALL PrOut
LD A,(PageN) ;put out page
LD HL,POff
ADD (HL) ;adjust for "=" option
LD L,A
LD H,0
LD DE,PNBuf
CALL BCDCon
LD HL,PNBuf
LD B,5
CALL POStr
CALL PCRLF
CALL PCRLF ;two blank lines
CALL PCRLF
NPnoh: POP HL
POP BC
LD A,(PgLen) ;reset TOP
LD B,A
OR A
RET
NPquit: POP HL
POP BC
SCF
RET
PNBuf: DB 'nnnnn',0 ;(also used elsewhere)
;
DotChk: CP A,CR ;may ignore dot commands
JR Z,DotCCR
CP A,'.'
JR Z,DotCDt
DtC01: EX AF,AF' ;ordinary char
LD A,(IgnFlg)
CP 0FFh ;ignoring chars?
RET Z ;(returns 0FFh, nonprinting)
XOR A
LD (IgnFlg),A ;nope, clear dot search
DtCRet: EX AF,AF' ;no action, accept char
RET ;leave it 0FFh (ignore)
DotCCR: CALL DtC01
EX AF,AF'
LD A,1 ;1 = ready to ignore if next char dot
LD (IgnFlg),A
EX AF,AF'
RET
DotCDt: EX AF,AF'
LD A,(FMode) ;Only ignore dotcmds in "W" mode
CP 'W'
JR NZ,DtCRet
LD A,(IgnFlg)
OR A
JR Z,DtCRet
LD A,0FFh ;FF = dot seen, ignore
LD (IgnFlg),A
RET
;
ChekC: CP ' ' ;may mask ctl chars
RET NC
CP CR ;exceptions: CR,LF,BadTbl
RET Z
CP LF
RET Z
PUSH HL
PUSH BC
LD HL,BadTbl
LD BC,BadLen
CPIR
POP BC
POP HL
RET Z
PUSH AF
LD A,(POByt)
BIT 2,A
JR NZ,CMask
POP AF
RET
CMask: LD A,'^' ;mask: print "^",
CALL PrOut
POP AF
OR 40H ;turn ^A into A, etc.
RET
;
PrOut: CP 0FFH ;(FF=dummy code, ignore)
RET Z
PUSH BC ;Print byte
PUSH DE
PUSH HL
LD HL,POByt ;printing yet?
BIT 6,(HL)
JR NZ,Sk2PO
CP ' '
JR NC,Sk1PO ;non-ctl
LD HL,BadTbl
LD BC,BadLen
CPIR
JR Z,Sk2PO ;ILLEGAL
LD HL,TogTbl
LD BC,4
CPIR ;toggle?
JR Z,Sk3PO
LD BC,4
CPIR ;switch?
JR NZ,Sk1PO ;arbitrary ctl-code
LD A,4-1
SUB C ;nontog# (0..n)
ADD A
ADD A
ADD A ;*8
LD E,A
LD D,0
LD HL,UCodes
ADD HL,DE
Sk00PO: LD B,(HL)
INC HL ;string to send
Sk0PO: CALL LSTStr
JR Sk2PO
Sk3PO: LD A,4-1
SUB C ;tog# (0..n)
ADD A
ADD A
ADD A
ADD A ;*16
LD E,A
LD D,0
LD HL,PCodes
ADD HL,DE
BIT 7,(HL) ;toggle status?
JR NZ,Sk3aPO
LD B,(HL) ;off, turn on
SET 7,(HL)
INC HL
JR Sk0PO
Sk3aPO: RES 7,(HL) ;on, turn off
LD DE,8
ADD HL,DE
JR Sk00PO
Sk1PO: LD E,A ;byte to send
PUSH AF
CALL LSTOut
POP AF
CP LF
CALL Z,DoPOf ;LF? need margin skip
Sk2PO: POP HL
POP DE
POP BC
RET
;
DoPOf: LD A,(PrLMrg) ;do printer margin offset
OR A
RET Z
LD B,A
DoPOfL: LD A,' '
CALL PrOut
DJNZ DoPOfL
RET
;
PCRLF: LD A,CR ;do CR(LF?)
CALL PrOut
PLF: LD A,(LFChr)
JP PrOut
;
POStr: LD A,B ;send B chars at (HL) to PrOut
OR A
RET Z
LD A,(HL)
CALL PrOut
INC HL
DJNZ POStr
RET
;
LSTStr: LD A,B ;send B chars at (HL) to LST directly
OR A
RET Z
LD E,(HL)
PUSH BC
PUSH HL
CALL LSTOut
POP HL
POP BC
INC HL
DJNZ LSTStr
RET
;
LSTOut: LD C,LSTO ;print char in E
JP BDOSep
;
;
;
; ASSORTED SUPPORT ROUTINES
;
;RAM initialization functions
;
IniRAM: LD HL,MnuEnd ;Figure what used to be TxtOrg
LD A,(Help) ;help menus disabled?
OR A
JR NZ,IniR02
LD HL,VDEend ;yes, use that memory for editing
IniR02: LD (BegTx),HL
LD HL,(BDOSep+1) ;BDOS origin (xx06)
LD L,-4 ;a few bytes room
DEC H ;back a page
LD (EndTx),HL
XOR A ;initialize screen
LD (NSkip),A
INC A
LD (Horiz),A
LD (Vert),A
LD (CurCol),A
LD HL,1
LD (CurPg),HL
LD (CurPgL),HL
LD (CurLin),HL
LD HL,(BegTx) ;set up cursor gap, mark CRs at ends
DEC HL
LD (BefCu),HL
LD (HL),CR
LD HL,(EndTx)
INC HL
LD (AftCu),HL
LD (HL),CR
RET
;
;Case selection subroutine
; CALL Case
; DB # of entries in list
; DW Default subroutine if no match
; DB value1
; DW subroutine1....
; <return point>
;
Case: POP HL
LD B,(HL) ;entries
INC HL
LD E,(HL) ;DE=default sbr
INC HL
LD D,(HL)
INC HL
Lp1Ca: CP (HL) ;Value matches?
INC HL
JR NZ,Sk2Ca
LD E,(HL) ;yes, get address
INC HL
LD D,(HL)
JR Sk3Ca ;finish up
;
Sk2Ca: INC HL ;No match, skip ahead
Sk3Ca: INC HL
DJNZ Lp1Ca ;Try again
EX DE,HL ;Swap sbr and return
PUSH DE ;Store return (end of list)
JP (HL) ;Go do sbr (LAST match)
;
;
XCase: CALL UCase ;force A to ctl-codes
CP '@'
RET C
CP '_'+1
RET NC
AND 1FH
RET
UXCase: CP ESC ;uppercase A if letter OR ctl-code
JR NC,UCase
ADD 40H
RET
UCase: CP 'a'
RET C ;uppercase A if letter
CP 'z'+1
RET NC
AND 5FH
RET
;
;
Wait: LD A,(MacFlg) ;Macro Pause function
OR A
JP Z,Error2
LD A,3 ;Wait about 3/2 sec
JR Dly0
;
Delay: LD B,A ;Delay about A/2 sec
LD A,(MacFlg) ;but NOT if Macro going
OR A
RET NZ
LD A,B
Dly0: ADD A
ADD A
Dly1: PUSH AF
CALL BDly
POP AF
DEC A
JR NZ,Dly1
RET
BDly: LD A,(MHz)
LD B,A
LD C,0
BDlyLp: DEC BC
LD A,B
OR C
JR NZ,BDlyLp
RET
;
;
; UR-ROUTINES
;
Fill: LD (DE),A ;fill B bytes at DE with A
INC DE
DJNZ Fill
RET
;
SubDP: PUSH HL ;Double precision subtract
OR A ;BC = HL - BC + 1
SBC HL,BC
LD B,H
LD C,L
INC BC
POP HL
RET
;
BgCnt: LD HL,(BegTx) ;Count bytes before cursor
LCnt: LD B,H
LD C,L
PUSH HL
LD HL,(BefCu)
CALL SubDP
POP HL
RET
NdCnt: LD HL,(EndTx) ;Count bytes after cursor
RCnt: LD BC,(AftCu)
JR SubDP
;
GpCnt: LD BC,(BefCu) ;Count cursor gap size
LD HL,(AftCU)
DEC HL
DEC HL
JR SubDP
;
;Move bytes across cursor gap so the gap moves left.
;HL points to what will become BefCu.
;
MoveL: CALL LCnt ;bytes to move
RET C
LD HL,(AftCu)
DEC HL
EX DE,HL
LD HL,(BefCu)
LDDR
LD (BefCu),HL
EX DE,HL
INC HL
LD (AftCu),HL
RET
;
;MoveR - Moves gap right. HL will become BefCu.
;
MoveR: CALL RCnt
RET C
LD HL,(BefCu)
INC HL
EX DE,HL
LD HL,(AftCu)
LDIR
LD (AftCu),HL
EX DE,HL
DEC HL
LD (BefCu),HL
RET
;
;CrLft - Find CRs to left of cursor (up to E)
;
CrLft: CALL BgCnt
JR NC,Sk1Lf
XOR A ;no bytes, return with C and no Z
SUB 1
RET
Sk1Lf: CALL FetchB
CP CR ;Is cursor on a CR
JR NZ,Sk2Lf
LD A,1
CP E
JR NZ,Sk2Lf
SCF ;Asked for 1, and already there: ret C and Z
RET
Sk2Lf: LD A,CR
Lp3Lf: CPDR ;find a CR
JP PO,Sk4Lf ;count exhausted?
DEC E
JR NZ,Lp3Lf ;Do more?
INC HL ;Back up to before CR
INC HL
XOR A ;Found AOK, ret Z and no C
RET
Sk4Lf: INC HL ;Back to first byte
SCF
CCF ;Clear C
JR Z,Sk5Lf ;Was first byte CR
DEC E ;No, reduce count
RET
Sk5Lf: INC HL ;Back after CR
DEC E ;the one we wanted?
RET Z
DEC HL ;No, back in front of it
DEC E
RET
;
;CrRit - same, to right.
;
CrRit: CALL NdCnt
JR NC,Sk1Ri
XOR A
SUB 1 ;no bytes, return C and no Z
RET
Sk1Ri: LD D,E
LD A,CR
LD HL,(AftCu)
Lp2Ri: CPIR
JP PO,Sk3Ri
DEC E
JR NZ,Lp2Ri
SCF
CCF ;found AOK, ret Z and no C
RET
Sk3Ri: LD A,D
CP E
JR NZ,Sk4Ri
SCF ;none found, return C and Z
RET
Sk4Ri: LD HL,(EndTx)
DEC HL
LD A,CR
LD BC,0FFFFh
CPDR
INC HL
INC HL
OR 1 ;some but not enough, ret no C and no Z
RET
;
;cursor positioning subroutines
;
TopV: LD A,1
JR LoadV
MidV: LD A,(TxtLns)
SRL A
JR LoadV
DecV: PUSH HL
LD HL,(CurLin)
DEC HL
LD (CurLin),HL
POP HL
DecVO: LD A,(Vert) ;returns Z if cannot Dec
CP 1
JR Z,LoadV
DEC A
JR LoadV
IncV: PUSH HL
LD HL,(CurLin)
INC HL
LD (CurLin),HL
POP HL
IncVO: LD A,(Vert) ;returns Z if cannot Inc
PUSH HL
LD HL,TxtLns
CP (HL)
POP HL
JR Z,LoadV
INC A
JR LoadV
BotV: LD A,(TxtLns)
LoadV: LD (Vert),A
RET
LftH: LD A,1
JR LoadH
LTabH: LD A,(Horiz)
DEC A
JR Z,RitH
CALL WhatC ;ouch, got to calculate
LD HL,NSkip ;Horiz = CurCol-NSkip
SUB (HL)
JR C,RitH
JR LoadH
DecH: LD A,(Horiz)
DEC A
RET Z
JR LoadH
TabH: LD A,(Horiz)
DEC A
PUSH HL
LD HL,TabCnt
OR (HL)
POP HL
INC A
JR IncT
IncH: LD A,(Horiz)
IncT: PUSH HL
LD HL,View
CP (HL)
POP HL
RET NC
INC A
JR LoadH
RitH: LD A,(View)
LoadH: LD (Horiz),A
RET
;
;
;Get next text character from memory
;(HL and C keep track across repeated calls)
;
GetNx: XOR A
CP C ;Have we a hidden space?
JR NZ,Sk1Gt
LD A,(HL) ;No, get next byte
INC HL
BIT 7,A ;Does it have hidden space?
JR Z,Sk2Gt
AND 07Fh ;Yes, note and remove
INC C
JR Sk2Gt
Sk1Gt: DEC C ;Fetch hidden space
LD A,' '
Sk2Gt: CP CR ;Set Z flag if CR
RET
;
;Hide any hideable spaces. (NEW ALGORITHM)
;
Cmprs: CALL BgCnt ;bytes to left
JR C,Sk2Cm ;none?
LD D,H
LD E,L
DEC DE
Lp1Cm: LD A,(HL) ;Get a byte
CP ' ' ;Nonspace? fine
JR NZ,Sk1Cm
LD A,(DE) ;Last byte CTL? fine
CP 20H
LD A,' '
JR C,Sk1Cm
LD A,(DE) ;Hidden space already? fine
BIT 7,A
LD A,' '
JR NZ,Sk1Cm
LD A,(DE)
OR 80h ;Got to hide the space.
DEC DE
Sk1Cm: INC DE ;Store byte
LD (DE),A
INC HL ;Bump input
DEC BC
LD A,B
OR C ;more to do?
JR NZ,Lp1Cm
LD (BefCu),DE ;This is now BefCu
;
Sk2Cm: CALL NdCnt ;How many after cursor?
RET C
LD HL,(EndTx) ;work back from end
LD D,H
LD E,L
INC DE
Lp3Cm: LD A,(DE)
CP ' ' ;Last byte space?
JR NZ,Sk3Cm
LD A,1FH ;This byte CTL?
CP (HL)
JR NC,Sk3Cm
BIT 7,(HL) ;This byte already hiding?
JR NZ,Sk3Cm
SET 7,(HL) ;Got to hide that space
INC DE
Sk3Cm: DEC DE
LD A,(HL) ;Store byte
LD (DE),A
DEC HL ;Bump input
DEC BC
LD A,B
OR C ;more to do?
JR NZ,Lp3Cm
LD (AftCu),DE ;This is now AftCu
RET
;
;Set BC to gap size (make room if needed, or set EdErr)
;
Space: LD L,A ;Save A
PUSH HL
CALL GpCnt ;Count gap size
CALL C,Cmprs ;No room? Hide spaces
CALL GpCnt ;Room now?
CALL C,Error1
POP HL
LD A,L
RET
;
;Put ordinary byte in A into text at cursor.
;
Insrt: CALL Space ;Insert Before cursor
RET C
LD HL,Modify
LD (HL),0FFh
Insrt1: LD HL,(BefCu) ;Bump pointer
INC HL
LD (HL),A ;Store byte
LD (BefCu),HL
OR A ;Clear flags
RET
InsrtA: CALL Space ;same, but After cursor
RET C
LD HL,Modify
LD (HL),0FFh
InsrA1: LD HL,(AftCu)
DEC HL
LD (HL),A
LD (AftCu),HL
OR A
RET
;
;Compute absolute line number
;
CountS: LD HL,1 ;Hard way: from start
LD (CurLin),HL
CALL BgCnt
JR Sk0CL
CountL: LD HL,(LastCu) ;same but faster, using LastCu
INC HL
CALL LCnt
Sk0CL: RET C ;(At start, or have not moved)
LD DE,0
LD A,CR
LD HL,(BefCu)
Lp1CL: CPDR
JR NZ,Sk1CL
INC DE
JP PE,Lp1CL
Sk1CL: LD HL,(CurLin)
ADD HL,DE
LD (CurLin),HL
RET
CountR: LD HL,(LastCu) ;same, but for backward move
DEC HL
CALL RCnt
RET C ;(have not moved)
LD DE,0
LD A,CR
LD HL,(AftCu)
Lp1CR: CPIR
JR NZ,Sk1CR ;(have not moved)
INC DE
JP PE,Lp1CR
Sk1CR: LD HL,(CurLin)
OR A
SBC HL,DE
LD (CurLin),HL
RET
;
;
;MACRO functions
;
MacKey: LD HL,KeyQ
CALL Prompt
CALL RptKey ;which key?
CALL UCase
LD (MKsav),A
CP 'N' ;no-rpt request?
JR Z,MK0
CP 'Q' ;no-rpt & macro request?
JR NZ,MK00
MK0: CALL Echo ;show N or Q, get next
CALL RptKey
MK00: SUB '0'
JP C,Error7
CP 10
JP NC,Error7
LD D,A ;save key
LD A,0FFH
LD HL,MacStr
LD BC,StrSiz+1 ;find end
CPIR
LD A,StrSiz
SUB C ;figure length
LD E,A ;save it
LD HL,Keys+2
LD A,D
OR A
JR Z,MKlp1F
MKlp1: LD C,(HL)
LD B,0 ;find key in list
ADD HL,BC
INC HL
DEC A
JR NZ,MKlp1
MKlp1F: LD A,(HL) ;old length
OR A
JR Z,MK1
PUSH DE
PUSH HL ;delete old one
LD E,(HL)
LD D,0
LD (HL),0
INC HL
EX DE,HL
ADD HL,DE
LD B,H
LD C,L
PUSH HL
LD HL,Keys+200H
OR A
SBC HL,BC ;bytes to move
LD B,H
LD C,L
POP HL
LDIR
CALL VerKey
POP HL
POP DE
MK1: LD A,E ;anything to add?
OR A
JR Z,MKDone
LD A,(Keys+1) ;will it fit
OR A
JR NZ,MK1a
LD A,(Keys)
SUB E
JP C,Error1
MK1a: LD (HL),E ;yes
INC HL
LD C,E
LD B,0
PUSH HL
LD HL,Keys+200H-1
LD D,H
LD E,L
OR A
SBC HL,BC ;from here
POP BC
PUSH HL
SBC HL,BC ;bytes to move
LD B,H
LD C,L
INC BC ;inclusive
POP HL
LDDR ;make room
LD C,(HL)
LD B,0
INC HL
EX DE,HL
LD HL,MacStr
PUSH DE
LDIR ;insert new one
POP HL
LD A,(MKsav)
CP 'N' ;take care of N/Q request
JR Z,MK2
CP 'Q'
JR NZ,MKDone
DEC HL
LD A,(HL) ;Q only works if length >1
CP 2
INC HL
JR C,MK2
INC HL
SET 7,(HL) ;indicate quiet
DEC HL
MK2: SET 7,(HL) ;indicate no-rpt
MKDone: CALL VerKey
JP ShoLn1
;
;
VerKey: LD B,10 ;verify key area
LD HL,200H-12
LD D,0
LD IX,Keys+2
VKlp: LD A,StrSiz ;check size
CP (IX)
JR C,VKwipe
LD E,(IX)
SBC HL,DE ;decrement
JR C,VKwipe
ADD IX,DE ;move to next
INC IX
DJNZ VKlp
LD (Keys),HL ;free bytes
LD A,H
OR L
RET Z ;full?
VKlp2: LD (IX),0
INC IX ;zero fill
DEC HL
LD A,H
OR L
JR NZ,VKlp2
RET
VKwipe: LD HL,200H-12 ;oops, bad
LD (Keys),HL
LD IX,Keys+2
LD HL,200H-2
JR VKlp2
;
ChainK: LD HL,MacFlg ;chain to new macro
BIT 0,(HL) ;(used only if macro going)
RET Z
CALL RptKey ;get key#
CP '0'
JP C,Error8
CP '9'+1
JP NC,Error8
PUSH AF
CALL Loud
XOR A
LD (MacFlg),A
POP AF
JR UK0
;
UseKey: LD HL,MacFlg ;macro going already?
BIT 0,(HL)
RET NZ ;YES, this is just a label
UK0: SUB '0' ;NO, retrieve key 0-9
LD B,A
LD HL,Keys+2
JR Z,UKlp1F
UKlp1: LD E,(HL)
LD D,0 ;find it
ADD HL,DE
INC HL
DJNZ UKlp1
UKlp1F: LD A,(HL) ;length
INC HL
OR A
JP Z,Error7 ;none?
LD C,A
LD B,0
PUSH BC ;on stack for Mac00 entry
LD DE,DMA
PUSH DE
LDIR ;fetch it in
POP HL ;point to it
BIT 7,(HL)
RES 7,(HL)
JR Z,Mac00 ;not no-rpt? go ask, etc.
INC HL
BIT 7,(HL)
RES 7,(HL)
CALL NZ,Quiet ;quiet?
LD A,'1'
JR Mac0 ;go do just once
;
DoMac: LD HL,MacroQ ;get Macro defn
CALL Prompt
CALL GetStr
OR A
JR Z,MacDel ;none? delete
LD C,A ;save count
LD B,0
PUSH BC
Mac00: LD HL,RptcQ ;(entry for normal Key)
CALL Prompt
CALL RptKey
CALL UCase
CP 'Q'
JR NZ,Mac0
CALL Echo
CALL Quiet ;Q? do quiet, get rpt cnt
CALL RptKey
Mac0: POP BC ;string cnt (entry for no-rpt Key)
PUSH AF ;save rpt cnt
LD A,C
OR A ;null string?
JR Z,Mac1
LD HL,DMA ;move in string
LD DE,MacStr
LDIR
EX DE,HL
LD (HL),0FFh ;terminator
Mac1: CALL ShoLn1
POP AF
LD B,255
CP '*' ;figure rpt cnt
JR Z,Mac2 ;(* is maximal)
LD B,0 ;(0 is default)
SUB '0'
JR C,Mac2
CP 9+1
JR NC,Mac2
LD B,A
Mac2: LD A,B ;set rpt cnt
LD (RptCnt),A
OR A
JP Z,Loud ;oops, rpt=0
Mac3: LD HL,MacStr ;Point to it
LD (CmdPtr),HL
LD A,0FFH ;Okay, here goes
LD (MacFlg),A
LD HL,InsFlg ;save INSERT toggle
LD A,(HL)
LD (SavIns),A ;turn INSERT off if on
BIT 7,(HL)
CALL NZ,IToggl
RET
MacDel: LD A,0FFH
LD (MacStr),A
JP ShoLn1
;
;"Macro Programming Language"
;
MacJmp: LD A,(MacFlg) ;jump to a label
OR A
JP Z,Error8 ;macro must be going
LD (JmpFlg),A ;say Jump in progress
CALL RptKey
LD HL,JmpFlg
LD (HL),0
CP '[' ;TOF/EOF?
JR Z,MJtop
CP ']'
JR Z,MJend
CP '>' ;move/loops?
JR Z,MJRt
CP '<'
JR Z,MJLf
LD E,A ;key to find
LD HL,MacStr
LD B,StrSiz
MJlp: LD A,(HL) ;search along
INC HL
CP 0FFH
JP Z,Error8
CP ESC
JR Z,MJlp01
DJNZ MJlp
JP Error8
MJlp01: LD A,E ;found ESC... right one?
CP (HL)
JR NZ,MJlp
INC HL ;yep
LD (CmdPtr),HL
RET
;
MJtop: LD HL,MacStr ;redo it from the top
LD (CmdPtr),HL
RET
MJend: XOR A ;quit
LD (MacFlg),A
LD E,A
CALL RstIns
JP Loud
MJRt: CALL NdCnt ;right/left jump loops
JP C,Error7 ;stop at EOF
CALL Right
JR MJredo
MJLf: CALL BgCnt
JP C,Error7
CALL Left
MJredo: LD HL,(CmdPtr)
DEC HL ;back up to the ESC to repeat
DEC HL
DEC HL
DEC HL
LD (CmdPtr),HL
RET
;
MacTst: LD A,0CAH ;(JP Z)
JR MacT1
MacTsX: LD A,0C2H ;(JP NZ)
MacT1: LD (MacT),A
LD A,(MacFlg)
OR A ;macro must be going
JP Z,Error8
CALL RptKey ;get char to match
LD E,A
CALL Fetch ;char at cursor
CP E
MacT: JP Z,MacJmp ;yes? jump <--- can be JP NZ too
JP RptKey ;no, just eat label
;
;Get the next key stroke (check Macro first.)
;
TRptKy: XOR A ;enable redisp Timer
JR RK0
RptKey: LD A,0FFH
RK0: LD (KeyFlg),A
LD A,(MacFlg)
OR A ;macro waiting?
JP Z,KeyIn ;no.
MacIn: CALL Keybd ;YES, check keyboard for abort
CP ESC
JR NZ,MacIn1
LD HL,(CmdPtr) ;abort, make this last char
LD E,(HL)
JR MacIn3
MacIn1: LD HL,(CmdPtr) ;OK, take waiting char
LD E,(HL)
INC HL ;bump pointer
LD (CmdPtr),HL
LD A,(HL) ;end of macro now? (FF)
INC A
JR NZ,MacIn2 ;NO, return char
LD A,(JmpFlg) ;jump in progress?
OR A
JR NZ,MacIn2
LD HL,RptCnt ;need to repeat?
LD A,(HL)
INC A
JR Z,McIn1a
DEC (HL)
JR Z,MacIn3
McIn1a: LD HL,MacStr ;repeat: reset pointer
LD (CmdPtr),HL
MacIn2: LD A,E
AND 7FH ;strip parity, return char
RET
MacIn3: PUSH DE ;NO, stop macro execution
XOR A
LD (MacFlg),A
CALL RstIns ;note E=last char (may be ^V!)
CALL Loud
POP DE
JR MacIn2
;
;Unconditional Q/L for Macros
;
IF VDM
ShutUp EQU PutCh ;where to RET out
ELSE
ShutUp EQU CONOut
ENDIF
;
Quiet: LD HL,ShutUp
LD (HL),0C9H ;(RET)
RET
Loud: LD HL,ShutUp
XOR A ;(NOP)
CP (HL)
RET Z
LD (HL),A
JP HoldSc ;gotta see...
;
RstIns: LD A,E ;restore INSERT status after Macro
CP 'V'-40h
LD A,(InsFlg)
JR NZ,RstI1
CPL ;kludge for last char ^V
RstI1: LD HL,SavIns
CP (HL)
CALL NZ,IToggl ;if it has changed
RET
;
;Conditional Q/L for formatting etc.
;
;
XQuiet: LD HL,ShutUp
LD A,(HL)
LD (HL),0C9H ;(RET)
LD (SavQ),A
RET
XLoud: LD A,(SavQ)
OR A ;(NOP)
RET NZ
LD (ShutUp),A
RET ;do NOT need redisp here
;
;Force loud for header display
;
Force: LD HL,ShutUp
LD A,(HL)
LD (HL),00H ;(NOP)
LD (SavQ2),A
RET
UForce: LD A,(SavQ2)
CP 0C9H ;(RET)
RET NZ
LD (ShutUp),A
RET
;
;
;END of Module 1