home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug144.arc
/
EASE16.LBR
/
EASE.MZN
/
EASE.MAN
Wrap
Text File
|
1979-12-31
|
45KB
|
1,999 lines
A short manual for Ease version 1.6
-----------------------------------
Contents:
Section 1: Ease in general.
Section 2: The editor.
Section 3: The options.
Section 4: Running in high memory.
Section 1:
What is this Ease program anyway?
It's one piece of software that allows you to edit the commands
that you are entering and have entered. If you make a typo,
you can go back and get the line right without retyping it. If
ZCPR33 encounters a problem with a command that you type, you can
make whatever changes are necessary for it to be correct and
then re-execute the line.
Ease is a shell which allows you to edit the command you're typing:
Ease provides a bunch of commands that the BDOS line input
function (what you use to send commands to ZCPR3 when you don't
use Ease or HSH or VCED) doesn't have the smarts to. Commands
like word forward, word back, delete word or line or character.
In fact Ease provides a fairly large subset of the commands of
whatever editor you are using to change documents (eg. WordStar,
NewWord, Perfect Writer, Mince, etc.). And whatever word
processor you use, Ease can be made to use the same commands.
And to recall and edit the commands you have typed:
Using Ease, you can step backward through your commands or
search for a specific command, no matter how long ago it was
typed. You can then edit it and re-execute it.
Ease is an error handler because there isn't much to an error
handler, other than an editor:
The majority of the 4k that Ease takes up is its editor. Or
rather, if you took out all the text messages that the error
handler needs, it would be. But an error handler's a real simple
thing, so making Ease an error handler as well as a shell was no
big thing. And because it's all one program, it takes only one
file on your disk.
Section 2:
I don't particularly like WordStar.
Ease has a lot of code in it. But the part which you actually
have to deal with is the editor. If that editor rubs you the
wrong way, you won't like the program. To insure that you
will like it, Ease provides you with a way of changing the
command keys.
WordStar commands have become the standard for ZCPR3. I think
Emacs commands would be infinitely preferable. I provide Ease
with WordStar command keys, but I'd rather you set them to
emulate whatever you're comfortable with than leave them in the
state they're in.
At the bottom of Ease (at the start of the program) is a list
of commands and the keystrokes which make them happen. By
changing this table, you change Ease.
Actually patching:
Use a patch program to change the Command file. Steve Cohen's
Z-Patch is very good. Go to the first page and look what you
see.
Something akin to:
...Z3ENV......EASE VAR......Q..D..S..E..X..A..F..
Period represents "Whatever". Or in other words, I don't know
what you'll see where I put the periods. It doesn't matter.
Most (not all) of the places where I put periods should NEVER be
changed.
The changeable stuff:
EASE VAR......Q..D..S..E..X..A..F........G..H.....T.....R.....Y..U..B..
^^^^^^^^^^^^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
The changeable stuff starts at "EASE VAR" (location 0Eh in
relation to the start of the file). That's the name of the
command history file. If you don't like it, change it. Be sure
to think out it as "FILENAMETYP" and not a file name as you type
it at the ZCPR3 or Ease prompt. Fill out the first eight
characters of the name (padding with spaces if necessary) and
then the 3 character type.
The next changeable location is the byte following "VAR".
(Location 19h) It contains a 50 (hexidecimal, which is 80
decimal) in the release version and represents the number of
characters in a single line. If you have a 40 column display,
change this to 28. If you have a 132 column display, change it
to 84.
The next number is a zero (At 1Ah)--it's padding for the screen
width number, just skip it.
The number following this zero is a 2. (At 1Bh) It represents
the length which a command must be to be stored in the history
file. If a command is two characters or less (as released), it
will be discarded. You could make this number bigger or
smaller, depending on your preferences. Smaller would include
drive changes (eg. B:) and bigger would exclude the more often
used commands (eg. DIR, CLS, etc.).
The next number is another padding zero. (At 1Ch) Just skip it.
The number at 1Dh is the flag GOBEGFLG. Set it to zero if
you want he cursor at the end of a line when you use ^B or ^O or ^N.
Set it to 0FFh if ytou want the cursor at the begining of the line.
1Eh is also a flag (BEEPFLG). Set it to 0FFh to beep on an error,
zero to be silent.
1Fh is the SMARTSAV flag. Set it to 0FFh if you don't want to
save those commands which you called up with a ^O, ^B or ^N and
haven't modified. Set it to zero if you want all commands saved.
With this set, you might be in a position when ^B would call up
something other than your last command typed.
Skip the next three. (20h, 21h, 22h) They will be used in
later versions of EASE. Skip the next three as well, they describe
the command table. (23h, 24h, 25h)
And now we get to the three character Key/Command entries.
The first character is a letter, the second and third make up a
location (ie. a command). You can change the character to
anything you want.
Byte: -- Corresponds to:
'A' -- ^A
'A' + 80h -- (<Meta key> and ^A) or (<Meta key> and A)
7Fh -- Delete key
The Meta Key is the single prefix key you can use with Ease.
In Emacs emulations, the Meta key is usually escape. In
WordStar, it's ^Q for most of the functions that Ease uses. So
by A + 80h, we mean a sequence of characters, namely (in the
distribution setup) ^Q ^A or ^Q A.
The functions which you can set your keystrokes for are:
SHIFTED -- Meta Key (Location 26h)
FCHR -- Right Char (29h)
BCHR -- Left Char (2Ch)
UP -- Up line (2Fh)
DOWN -- Down line (32h)
MBWORD -- Left word (35h)
MFWORD -- Right word (38h)
GOBOLN -- Start of line (3Bh)
GOEOLN -- End of line (3Eh)
FDEL -- Del char right (41h)
DELCHR -- Del char left (44h)
DELCHR -- Del char left (47h)
FDWORD -- Del word right (4Ah)
BDWORD -- Del word left (4Dh)
CMDKILL -- Kill to semi-colon (50h)
DELTOEND -- Delete to end of line (53h)
DELLIN -- Delete line (56h)
UNDO -- Reinsert deleted text (59h)
BACKLINE -- Back in history shell (5Ch)
NEXTLINE -- Forward in history file (5Fh)
BSEARCH -- Search for first char (62h)
TOGLIN -- Toggle insert (65h)
ITAB -- Insert Tab char (68h)
QINSERT -- Insert any char (6Bh)
REPLOT -- Redraw line (6Eh)
WARM -- Warm Boot (71h)
DONE -- End edit (73h)
QUITSH -- End EASE (76h)
After all that garbage is the punctuation (Location 74h), this
is the stuff that word functions are going to consider
non-letters. It ends with and includes the Tab (At location 91h).
So if you don't like the way that MFWORD goes about it's
business with respect to (for instance) colons, just place a
space over the colon. Or if you want it to think that double
quotes are punctuation, just put one on top of a character (maybe
the backslash) that you don't want as punctuation.
Section 3:
All right, never mind the keystrokes, what do the commands do?
Movement commands:
------------------
FCHR: Forward one char. If the cursor is at the end of
the line, it will "wrap" to the beginning of the line.
BCHR: Backward one char. If the cursor is at the
beginning of the line, it will "wrap" to the end
of the line.
UP: Go back the number of characters in a screen line
(the release package comes set to 80 chars for a
line). If there aren't enough chars to to up a
screen line, go to the beginning of the command line.
DOWN: Go forward the number of chars in a screen line.
If there aren't enough chars to go down a screen
line, go to the end of the command line.
MBWORD: Move back a word. Skip backwards over letters
until a punctuation character (usually including
space) is hit, then skip all punctuation until a
letter is hit. Punctuation is setable (see
section 1). "Wrap" if at beginning of line.
MFWORD: Move forward a word. "Wrap" if at end of line.
GOBOLN: Go to beginning of command line.
GOEOLN: Go to end of command line.
Deletion commands:
------------------
FDEL: Delete forward one character.
DELCHR: Delete backward a character. Two are supplied,
so Backspace and Delete may be used.
FDWORD: Delete a word Forwards.
BDWORD: Delete a word Backwards.
CMDKILL: Delete all chars until end of line or semi-colon.
DELTOEND: Delete until end of command line.
DELLIN: Delete entire command line.
UNDO: Insert chars from last line DELTOEND or DELLIN
Buffer Commands:
----------------
BACKLINE: Put the current line in the kill buffer (so you
can bring it back with UNDO) and put the
previous line in the history buffer on your
screen. If there is no previous line, the
console should Beep.
NEXTLINE: Put the current line in the kill buffer (so you
can bring it back with UNDO) and put the next
line in the history buffer on your screen. If
there is no previous line, the console should Beep.
BSEARCH: Search for a previous command starting with
whatever is on the command line. The current
line is put in the kill buffer, and if no line is
found, the console will Beep. This function
used to work differently. People complained.
Bizarre Commands:
-----------------
SHIFTED: The Meta key. All commands in Ease must be one
keystroke long. I cheated in the coding, to
make it simple. But that's very restrictive.
So Ease includes a Meta Shift key which turns on
a second set of commands. ^F does one thing,
Meta ^F does another. This is fairly
transparent to the user--He thinks he has
entered a sequence (eg. ^Q ^D (Go to the end of
the line)) when in fact, he has done two
separate commands. The first being to set the
Meta Switch. And the second to actually execute
the end of line command. Since the Meta switch
is on, the highbit of the command is set, and
the command table is searched for 'D' + 80h.
TOGLIN: Toggle insert. This command will set the prompt
to '}>', when in overwrite mode, or '>>' when in
insert mode. Overwrite mode inserts when it
hits the end of the line.
ITAB: Put a ^I (Tab) into the command. The tab key
(^I) is an oddball. It's the only control key
you have on your typewriter keyboard and expect
to be able to insert like a standard character.
So we need a special command for it.
QINSERT: Insert any character. After evoking this
command, hit the key key want in the text (this
is really only needed for control keys.
REPLOT: Redraw the line (just in case it gets scrambled).
This should only be necessary if you get line noise.
WARM: Cause a Warm Boot.
DONE: Execute the command line. If it is longer than
the user-setable maximum discard length, it will
be stored in the history file.
QUITSH: Pop the shell stack and quit Ease.
Section 4:
Why do I want it to run in high memory?
When you run a CP/M or ZCPR3 program, it usually does
everything in fairly low memory (from 100h up). And once you
leave a program, you might want to see what it did with that
memory or you might want to re-enter or SAVE the program you just
loaded into low memory with a GET or a program load. But if
your shell overwrites the program, you only have a shell program
down there.
So a shell should run in high memory and leave your normal
programs alone. The release version of Ease runs at 8000h.
This is a fairly high location which should leave most of your
smaller programs well enough alone.
If you want to change that number to a higher one (since you
have a higher TPA, which is to say more free memory, than I do)
go right ahead. You will need SLR's SLRNK (which I highly
recommend along with SLR's Z80ASM) or some other linker. A copy
of EASE.REL is contained in the release package. Just link it to
whatever location you want.
What is this Ease program anyway?
It's one piece of software that allows you to edit the commands
that you are entering and have entered. If you make a typo,
you can go back and get the line right without retyping it. If
ZCPR33 encounters a problem with a command that you type, you can
make whatever changes are necessary for it to be correct and
then re-execute the line.
Ease is a shell which allows you to edit the command you're typing:
Ease provides a bunch of commands that the BDOS line input
function (what you use to send commands to ZCPR3 when you don't
use Ease or HSH or VCED) doesn't have the smarts to.3 environment
ENVADDR:
dw 0f300h
dw ENTRY
defb version
; To go to the Error Handler, just
; go to START with error flag set.
;=============================================================================
;
; C O N F I G U R A T I O N A R E A
;
;=============================================================================
NAME: db 'EASE VAR' ; Command history file
WIDTH: dw 80 ; Length of line
TOOSHORT:
dw 02 ; Don't store in history
; if shorter than...
GOBEGFLG:
db 0ffh
BEEPFLG:
db 0ffh
DO_WRITE:
db 0ffh
NOP1: db 0 ; Future expansion
NOP2: db 0
NOP34: dw 0
TABLE: db [[LASTCASE - VECTOR] / 3] ; Number of cases
dw BEEP ; Default case ring bell
VECTOR: db 'Q'
dw SHIFTED ; Meta Key
db 'D'
dw FCHR ; Right Char
db 'S'
dw BCHR ; Left Char
db 'E'
dw UP ; Up line
db 'X'
dw DOWN ; Down line
db 'A'
dw MBWORD ; Left word
db 'F'
dw MFWORD ; Right word
db 'S'+80h
dw GOBOLN ; Start of line
db 'D'+80h
dw GOEOLN ; End of line
db 'G'
dw FDEL ; Del char right
db 'H'
dw DELCHR ; Del char left
db 127
dw DELCHR ; Del char left
db 'T'
dw FDWORD ; Del word right
db 127 + 80h
dw BDWORD ; Del word left
db 'R'
dw CMDKILL ; Kill to semi-colon
db 'Y'+80h
dw DELTOEND ; Delete to end of line
db 'Y'
dw DELLIN ; Delete line
db 'U'
dw UNDO ; Reinsert deleted text
db 'B'
dw BACKLINE ; Back in history shell
db 'N'
dw NEXTLINE ; Forward in history shell
db 'O'
dw BSEARCH ; Search for first char
db 'V'
dw TOGLIN ; Toggle insert
db 'I'
dw ITAB ; Insert Tab char
db 'P'
dw QINSERT ; Insert any char
db 'W'
dw REPLOT ; Redraw line
db 'C'
dw WARM ; Warm Boot
db 'M'
dw DONE ; End edit
db '_'+80h
dw QUITSH ; End EASE
LASTCASE:
PUNC: db ',.:!#%^&<>[]{}()_+-=`~/\|; ',tab
PUNCLEN equ $ - PUNC
;=============================================================================
;
; M A I N C O D E S E C T I O N
;
;=============================================================================
start:
ld hl,(envaddr) ; Get environment address
call z3init ; Initialize library routines
call z33chk
ret nz
call qerror ; See if error handler invocation
jp z,errorh ; If so, branch to error processing
call qshell
jp z,RUNSH ; Yes, don't install
;=============================================================================
;
; I N S T A L L A T I O N C O D E
;
;=============================================================================
; Program was invoked manually, so we need to set it up shell and error handler.
;----------------------------------------
; Subtask 1 -- determine whether to use a DU or a DIR prefix
;
; The program can examine the ZCPR33 option bytes to determine what features
; are supported (DU and/or DIR forms, which one first, wheel control over DU
; use, etc.). For now we will just assume that a DU prefix will be used and
; will omit coding this block.
;----------------------------------------
; Get user option: if null, do both. If E, then install the error handler
; else install the shell.
ld a,(5dh)
cp 'C'
jp z,RUNSH
call header
cp ' ' ; Error handler and shell
jr z,BOTH
cp 'E' ; Only error handler
jr z,ERRONLY
jr ISHELL ; Only the shell
BOTH: call ISHELL
;----------------------------------------
; Subtask 2 -- build error handling command line including directory prefix
; using data from the external FCB. We use the fact that the drive and user
; where the program was actually found along the path are stored in the
; command file control block. The user number is kept in the usual place;
; the drive is kept in the following byte. The drive is in the range 1..16
; (unless the command is resident, in which case the drive byte is 0).
ERRONLY:
call getmsg ; Get pointer to error command line
ld de,10h ; ..in message buffer
add hl,de
call PUT_NAME_TO_HL
call getquiet
ret nz
call CLPRINT
dc ' Error Handler'
jr P_CLST
ISHELL: call GETSH ; Is there a shell stack?
jr nz,SHFINE ; Yes
SHBAD: call CLPRINT
SHERR: dc 'Shell Error'
ret
SHFINE: ld hl,BUFFER
call PUT_NAME_TO_HL
call SHPUSH ; Store the shell name
jr nz,SHBAD ; Push to deep? Then abort
push hl
call SETFILE
call RECOVER ; Use existing file
call PUTSEC
pop hl
call getquiet
ret nz
PRWELC: call CLPRINT
dc ' Shell'
P_CLST: call PRINT
dc ': '
jp PSTR ; PRINT the string there and quit
RECOVER:
ld hl,SSEC
ld bc,BUFFER-SSEC-1
call ZERO
call SET
call OPEN
jr z,DELSET
DOFNO: call FNOWRITE
jr nz,DOFNO
call FNOWRITE
jr nz,DOFNO
jp BNOWRITE
DELSET:
ld c,19 ; Delete
call FBDOS
SET: xor a
ld (SSEC),a ; First sector
ld hl,SECBUF + 1 ; +1==So no long pause -- at least at first.
ld (SFP),hl
jp SAVETOWORK
PUT_NAME_TO_HL:
push hl ; Save pointer for way below
ex de,hl ; Switch pointer into DE
call getefcb ; Get address of the command FCB
inc hl ; Advance pointer to name of program
; Get drive user from Z33's FCB.
push hl
ld bc,13 ; Offset to drive number
add hl,bc ; HL now points to the drive number
; Here we get the drive where the program was found. Since we know that this
; is not a resident program, there is no need to check for a zero value.
ld a,(hl) ; Get it and
add a,'A'-1 ; ..convert to a letter
ld (de),a ; Save in error command line
inc de ; Increment command line pointer
dec hl ; Back up to user number
ld a,(hl) ; Get it and
call mafdc ; ..convert to decimal in command line
ld a,':' ; Put in the colon
ld (de),a
inc de
cont1:
pop hl ; Restore the pointer to the command name
ld bc,8 ; Copy 8 characters of name
ldir ; ..into error command line
xor a ; Store terminating null
ld (de),a
pop hl
ret
;=============================================================================
;
; E R R O R H A N D L I N G C O D E
;
;=============================================================================
; This is the main entry point for error handling
errorh:
ld a,(BEEPFLG) ; Did the user want a Beep?
or a
call nz,BEEP
;----------------------------------------
; Subtask 1 -- Display program signon message
task1:
call header
;----------------------------------------
; Subtask 2 -- Display system status
; This task determines whether ZEX and/or SUBMIT are running. Input
; redirection from either of them is turned off while error handling is
; performed (so user can provide the input).
task2:
call stopzex ; Stop ZEX input redirection
call CLPRINT
dc lf,tab,'(ZEX '
call getzrun ; Find out if ZEX is running
ld e,a
ld (ZEXORSUB),a
call ponoff ; Print on/off
call subon
jr z,task2a ; Branch if submit not supported
call PRINT
dc ', SUBMIT '
; See if submit is supported by the command processor
call stopxsub ; Stop XSUB input redirection
call getsrun ; Get submit running flag
call ponoff ; PRINT on/off
or e
ld (ZEXORSUB),a
; See if wheel byte is on or off
task2a:
call PRINT
dc ', WHEEL '
call getwhl
call ponoff
ld a,')'
call COUT
;----------------------------------------
; Subtask 3 -- Determine source of the error (internal or external) and
; display that information.
task3:
; call qerror
; ret nz ; If not an error, then don't show the rest
call CLPRINT
dc tab
call getcst ; Get command status flag
bit 3,a ; See if external command bit is set
jr nz,external ; Branch if external error
call PRINT ; "IN"ternal
dc 'In'
jr task3a
external:
call PRINT ; "EX"ternal
dc 'Ex'
task3a:
call PRINT ; "TERNAL ERROR"
dc 'ternal error #'
call xcmdoff ; Clear the external command bit (and ECP bit)
;----------------------------------------
; Subtask 4 -- Determine the error return code and display information about
; the nature of the error. This section of the code can be expanded to cover
; more error types as they are defined.
task4:
; call PRINT
; defb '#'
; defb 0
call getmsg
ld a,(hl) ; Get the error return code
push af ; Save for use below
call pafdc ; Display the number
call PRINT
dc ' -- '
pop af ; Get error code back
cp 14
jr c,OKERR
ld a,4
OKERR: add a ; Make 8 bit skip into 16 bit
ld e,a
ld d,0
ld hl,ERRSTRS - 2 ; Add to first string index
add hl,de
ld e,(hl)
inc hl
ld d,(hl) ; Pull in string location
ex de,hl
call pstr ; PRINT it
call CRLF
;----------------------------------------
; Subtask 5 -- Display bad command line
;
; In the final code, much more elaborate error processing would be performed
; here (or more likely, the code here will be used as a framework for existing
; error handlers).
task5:
call erradr ; Get pointer to bad command line
push hl ; Save for reuse below
ld de,BUFFER
scan: ; Find end of this command
ld a,(hl)
ld (de),a
or a ; See if end of command line buffer
jr z,GOTEND
cp ';' ; See if at command separator
jr z,task5a
inc hl ; Point to next character
inc de
jr scan ; Continue scanning
task5a:
push af
push hl
FILLREST:
inc hl
inc de
ld a,(hl)
ld (de),a
or a
jr nz,FILLREST
pop hl
pop af
GOTEND:
OKT5A: ld a,(hl)
ld (hl),0 ; Mark end of string
ld (delimptr),hl ; Save ptr to bad command's delimiter
ld (delim),a ; Store delimiter
push af
ld a,(ZEXORSUB)
or a
jp z,ERREDIT
call CLPRINT
dc tab,'Bad Command:',tab
pop af
pop hl ; Restore pointer to beginning of command
push af ; Save delimiting character
call pstr ; Display the bad command
pop af
or a
jr z,task6 ; If no rest of line, get out without output
push hl ; Save pointer to rest of command line
call CLPRINT
dc tab,'Rest of Line:',tab
pop hl
task5b:
dec hl ; Pt back to bad command delimiter
ld (hl),a ; Put semicolon back
inc hl
call pstr ; PRINT rest of command line
; AND RETURN!
;----------------------------------------
; Subtask 6 -- Deal with the bad command
; This is where the real error handling is performed. Here we just flush
; the entire command line and abort any submit job, but in a real error
; handler, several other functions would be performed. With normal command
; lines (ZEX and SUBMIT not running), the user has the following three basic
; choices: fix the bad command, skip the bad command, or abort the entire
; command line. If ZEX is running, there is an additional choice that should
; be available: abort the entire ZEX script. Similarly, if SUBMIT is running,
; the user must be given the option to abort the entire submit job.
; This code implements all of the above with the additional feature
; that if the bad command is the last on the line, the option to skip
; to next command is not presented as it would be meaningless.
task6:
call CLPRINT
dc cr,lf,tab,'(E)dit/(A)bort'
ld a,(delim) ; Get bad command delimiter
or a
jr z,task6a ; No trailing commands; skip next option
call PRINT
dc '/(C)ontinue'
task6a:
call PRINT
dc ': '
task6c: call capin ; get response
ld b,a ; Save for a moment
ld a,(delim) ; Get command delimiter again
or a
ld a,b ; Response back in A
jr z,task6b ; Don't allow 's' choice if no trailing command
cp 'C' ; Continue?
jr z,skip
task6b:
cp 'A' ; Abort?
jr z,abort
cp 'E' ; Edit?
jp z,edit
call beep ; Bad input
jr task6c
;-----------------------------------------------------------------------------
; Skip over bad command and resume with next in line
skip:
call getcl1 ; Pt to command line buffer
ld de,(delimptr) ; DE pts to bad command's delimiter
inc de ; Now pointing to next command
ld (hl),e ; Stuff address in
inc hl ; ..first two bytes
ld (hl),d ; ..of multiple command line buffer
call PRINT
defb 'Continuing...',1
ret ; Resume command execution with next command
;-----------------------------------------------------------------------------
; Abort (flush) command line
abort:
call abortmsg
call getzrun ; See if ZEX is running
jr z,abort2 ; Branch if not
; Deal with running ZEX script
call CLPRINT
dc tab,'Abort ZEX script (Y/N)? '
call getyesno ; Get user's answer
jr nz,abort1 ; Branch if negative response
call haltzex ; Abort ZEX
call abortmsg
jr abort2
abort1:
call abort3
; Deal with running SUBMIT job
abort2:
call getsrun ; Is a submit job running
ret z ; If not, return to command processor
call CLPRINT
dc tab,'Abort SUBMIT job (Y/N)? '
call getyesno ; Get user's answer
jr nz,abort3 ; Branch if negative response
call haltsub ; Abort SUBMIT
abortmsg:
call PRINT
defb 'Aborted',1
ret
abort3:
call PRINT
defb ' No',1
ret ; Back to command processor
;-----------------------------------------------------------------------------
; XCMDOFF -- turn off external command flag
; This routine turns off the external command bit and the ECP bit in the
; command status flag.
xcmdoff:
call getcst ; Get the command status flag
and 11110011b
; res 3,a ; Reset the external command bit
; res 2,a ; Reset the ECP bit also to prevent reentering
; ..the error handler on return
jp putcst ; Put new value back and return
;-----------------------------------------------------------------------------
; GETYESNO -- get yes/no answer from user
; Only 'Y' or 'y' accepted as affirmative answers. Routine returns Z if
; affirmative, NZ otherwise.
getyesno:
call capin ; Get user response
cp 'Y'
ret
;-----------------------------------------------------------------------------
; PONOFF -- PRINT ON or OFF in message
;
; If the Z flag is set on entry, 'OFF' is displayed; otherwize 'ON' is
; displayed.
ponoff:
jr z,poff
call PRINT
dc 'ON'
ret
poff:
call PRINT
dc 'OFF'
ret
; ------------------------------
; header -- PRINT program name and version
;
header: call CLPRINT
defb 'Z33 Error And Shell Editor, Vers. '
defb version / 10 + '0'
defb '.'
defb version mod 10 + '0'
dc betastage
ret
; ------------------------------
; CLPRINT -- PRINT CR LF and then following string.
CLPRINT:
call CRLF
jp PRINT
;-----------------------------------------------------------------------------
; Prompt -- PRINT a DU/DIR prompt.
;
PROMPT: call QPROMPT ; PRINT the DU:DIR
ld a,(INSFLG)
INSPROMPT:
or a
ld a,'>' ; For insert
jr nz,INSOK
ld a,'}' ; For no insert
INSOK: call COUT
ld a,'>'
jp COUT
QPROMPT:
call QERROR
jr nz,NOTERR
call PRINT
dc '[Error] '
NOTERR: call getmsg
ld bc,2eh
add hl,bc
ld c,(hl)
inc hl
ld b,(hl)
call getduok
jr z,NODU
ld a,b
add a,'A' ; Make it a letter
call COUT ; Write it
ld a,c
call pafdc ; Write it as a number
NODU: call dutdir ; Get the NDR
ret z
push hl
call getduok
ld a,':'
call nz,COUT ; And the colon to separate
pop hl
ld b,8 ; Eight chars max
NAMELOOP:
ld a,(hl) ; Get the first char
cp ' ' ; Is it the last
ret z ; YUP. done
call COUT ; Write it
inc hl
djnz NAMELOOP ; Repeat
ret
; -----------------------------------------------------------
; FillLine
; Check length of the new, edited, command line. If it will
; fit, copy it to the Z3 multiple command line buffer and
; return to the CPR to execute it. Otherwise, display error
; message and branch back to the editor.
GETLEN: ld hl,BUFFER
push hl
xor a
ld bc,302
cpir ; Find the ZERO
dec hl
pop de
push hl
sbc hl,de ; Get the length
ld b,h
ld c,l
pop hl
ret
FILL: xor a
call putcst ; No errors
call getcl1 ; Get Z3 command line addr in hl,
; ..length in a
cp c ; Compare with length of new line
jr c,FILLERR ; Branch if new line too long
ld a,b ; High order byte of length should be 0
or a
jr nz,FILLERR ; Branch if not
push hl ; Save Z3CL
ld de,4 ; Offset to first character in buffer
add hl,de
ex de,hl ; First char address in DE
pop hl ; Z3CL address in HL
ld (hl),e ; Store ptr to first command
inc hl ; At Z3CL
ld (hl),d
ld hl,BUFFER ; Get back pointer to new command
push hl
inc bc ; Adjust length to include trailing null
ldir ; Copy to system command line
call qerror
pop hl
ret z ; Return if it was an error
ld a,(SAVFLG)
or a
ret z ; Didn't change from read: Don't save
push hl
call GETLEN ; Get length again
ld hl,(TOOSHORT)
sbc hl,bc
pop hl
ret nc ; Too short to save
push hl
call OPEN ; Open 'er up
call SAVETOWORK ; Move the values around
call RRAND ; Read in the current record
xor a
call WFFILE ; Put the null to space the lines
pop hl
FILLWRITE:
ld a,(hl) ; Loop to put in the whole line
push hl
call WFFILE ; Put in the next char of the line
pop hl
ld a,(hl)
inc hl
or a
jr nz,FILLWRITE
call BNOWRITE
call PUTSEC
xor a
call WFFILE ; Write final spacer null
FLUSH: call WRAND
CLOSE: ld c,16 ; Close the file
FBDOS: ld de,FCB
jp BDOS ; Go back to CPR to execute it
FILLERR: ; To long for CCP to digest
call CLPRINT
defb bell,tab
defb 'Too long!',1
jr EDIT2
FINDSEC:
call getsh ; Get the sector number from the shell stack
ld bc,128
xor a
cpir ; Find the ZERO
ld a,(hl) ; ?? Must be 0 -- but it isn't -- It's the SEC
ret
GETSEC: call FINDSEC ; Put the new SEC to the saved var SEC
ld (SSEC),a
inc hl
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
ld (SFP),hl ; Put the File Pointer to saved FP
SAVETOWORK:
ld a,(SSEC) ; Move the saved vars to the working vars
ld (SEC),a
ld hl,(SFP)
ld (FP),hl
ret
PUTSEC: call FINDSEC ; Get location of SEC
ld a,(SEC)
ld de,(FP) ; Get SEC & FP
ld (hl),a
inc hl
ld (hl),e
inc hl
ld (hl),d ; Put the into the Shell Stack
ret
;-----------------------------------------------------------------------------
; Edit -- He, He, He...
;
ERREDIT:
pop af
pop hl
jr EDITNOE
EDIT: call PRINT
db 'Edit',1 ; PRINT the 'E' for edit choice
EDITNOE:
call CRLF
ld bc,BUFFER - ENDFLG - 1 ; Setup for zeroing out
jr SETUP
;--------------------------
; Run Shell (RUNSH) -- clear out the buffers and go to the editor.
RUNSH1: call CRLF
RUNSH: call GETSEC ; Get the sector number
ld a,1 ; Z3 Cmd line for ZEX
call putzex ; Make ZEX think we are Z3
ld bc,BUFFER - ENDFLG
SETUP: ld hl,INSFLG ; Fill and Zap
ld (hl),0ffh
inc hl
ld (hl),0ffh
inc hl
call ZERO ; Zero out to exhaustion of bc
EDIT2:
; ld hl,(envaddr) ; Get environment address
; call z3init
call OUTPUT1
ELOOP: xor a
ld (NOOUT+1),a ; OK for output
call GETKEY
ld b,a
ld a,(SHIFT) ; Get shift mask
or b
push af
xor a
ld (SHIFT),a ; Clear shift mask
pop af
cp ' '
jr c,CONTROL ; Yes, it's a command
cp 127
jr nc,CONTROL
call INSERT ; No, it's just a letter
jr ELOOP
CONTROL:
ld hl,ELOOP ; Return to...
push hl
ld de,TABLE ; Go to proper command
call UCASE
call acase2
SHIFTED:
ld a,10000000b ; Make shift mask set high bit
ld (SHIFT),a
ret
DELCHR: call DPOS ; Back up and delete forward
ret z
call DELETE
jp SHOWTOEND
FCHR: call FWRAP ; Go ahead a char and wrap if EOL
jp IPOS
FWRAP: ld hl,(POS) ; Check for forward wrap
ld a,(hl)
or a
ret nz
pop hl
jp GOBOLN
BCHR: call BWRAP ; Go back and wrap if BOL
jp DPOS
BWRAP: ld hl,(POS) ; Check for back wrap
dec hl
ld a,(hl)
or a
ret nz
pop hl
jp GOEOLN
MBWORD: call BWRAP ; Word forward with wrap
BWORD: call DPOS ; Word forward without
ret z
inc de
call PUNCCP ; Looking for punctuation
jr z,BWORD ; Skip punct
BWORD2: call DPOS
ret z
inc de
call PUNCCP ; Go till we hit punct
jr nz,BWORD2
dec de
jp IPOS
PUNCCP: ld hl,PUNC ; Check for punctuation
ld bc,PUNCLEN
cpir
ret
FDWORD: ld de,0 ; Delete forward a word
call FWORD ; Word forward
push de
FDWBACK:
ld a,d
or e
jr z,FDWENDBACK
dec de
call DPOS ; Back up same number of Chars
jr FDWBACK
FDWENDBACK
pop de ; Delete same number of chars
jr BDWRD1
BDWORD: ld de,0 ; Delete a word backwards
call BWORD
BDWRD1: ld a,d
or e
jp z,SHOWTOEND
dec de
push de
call DELETE ; Delete same number
pop de
jr BDWRD1
MFWORD: call FWRAP ; Forward word with wrap
FWORD: call IPOS
ret z
inc de
call PUNCCP ; Skip until punct
jr nz,FWORD
FWORD2: call IPOS
ret z
inc de
call PUNCCP ; Skip punct
jr z,FWORD2
dec de
jp DPOS ; Back up one
UP: ld hl,(WIDTH) ; Back 80 chars
BACKUP: ld a,h
or l
ret z
dec hl
push hl
call DPOS ; back up that many
pop hl
ret z
cp ' '
jr nc,BACKUP ; Control chars count double
ld a,h
or l
ret z
dec hl
jr BACKUP
DOWN: ld hl,(WIDTH) ; Go down a line
DOWNLOOP:
ld a,h
or l
ret z
dec hl
push hl
call IPOS ; Forward 'til hl = zero
pop hl
ret z
cp ' ' ; Control chars count double
jr nc,DOWNLOOP
ld a,h
or l
ret z
dec hl
jr DOWNLOOP
WARM: call DONEOUT
jp 0
DONE: pop hl ; Save it and run it
call DONEOUT
call GETLEN ; Get the length in BC
; call qerror ; Was it an error?
; jp z,FILLL2
ld a,(BUFFER)
cp ';' ; Comment?
jr z,JRUNSH
or a ; Empty?
jp nz,FILL ; Stuff the buffer
JRUNSH: call qerror
ret z
call qshell
ret nz
jp RUNSH1
FDEL: call DELETE ; Delete forward a char
ret z
jp SHOWTOEND ; Redisplay
QINSERT:
call GETKEY ; Get a key and insert it -- whatever it is
or a
ret z
jr IJP
ITAB: ld a,tab ; Insert a tab
IJP: jp INSERT
TOGLIN: ld hl,INSFLG ; Toggle the insert flag
ld a,(hl)
cpl
ld (hl),a
ld hl,(POS)
push hl
push af
call GOBOLN
call BACK
call BACK ; Back up to the begining and back to ICHAR
pop af
call INSPROMPT
pop de
TOGLP: ld hl,(POS) ; Go fwd to where we were
sbc hl,de
ret z
call IPOS
jr TOGLP
CMDKILL:
ld hl,(POS)
ld de,KILL
push de
ld bc,killlen ; Stop before NULL in KILL
ldir ; Move it
pop hl
CKL: push hl
call DELETE ; Delete to a semi-colon
pop hl
inc hl
cp ';'
jr z,CKDONE
or a ; Or a NULL
jr nz,CKL
CKDONE: ld (hl),0
jp SHOWTOEND ; Redisplay
DELLIN: ld hl,BUFFER
ld de,KILL
ld bc,killlen ; Stop at NULL in KILL
ldir ; Move it
DELLN1: call GOBOLN ; Go to start
DELTOEND:
call CLRTOEND ; Wipe everything on screen
ld hl,(POS)
ld (hl),0 ; Put a null at the start
ret
GOEOLN: call IPOS ; Move to end of line
jr nz,GOEOLN
ret
GOBOLN: call DPOS ; Move to start of line
jr nz,GOBOLN
ret
REPLOT: ld hl,(POS) ; RePRINT entire line
push hl
call GOEOLN ; Go to end and give us a CR LF
REPLT1: call CRLF
call OUTPUT ; Redisplay
pop de
GOTOPOS:
or a
call IPOS ; Move fwd to old position
sbc hl,de
ret z
jr c,GOTOPOS
GP2: call DPOS
ret z
sbc hl,de ; Done?
ret z
jr GP2
CAPIN: call cin
; Fall through to UPCASE
UCASE: push bc ; Upcase A
push af
and 80h
ld b,a
pop af
and 7fh ; Keep high bit
call UCASE2 ; Real upcase
or b
pop bc
ret
UCASE2:
cp ' ' ; Standard blah blah upcase funct
jr nc,NOTCTL
add '@'
NOTCTL: cp 'a'
ret c ; Not a lowercase
cp 'z'+1
ret nc ; Not a lowercase
sub ' ' ; Yes, a lowercase
ret
BSEARCH:
call OPEN ; Check for open, etc.
ld hl,(FP) ; Get our locations
ld a,(SEC)
push af
push hl
ld a,(ENDFLG) ; Did we hit the end?
or a
jr z,BBDONE
ld a,(BACKFLG) ; Did we back up right before this?
or a
jr nz,BBDONE
call BNOWRITE
jr z,BSRCHNO1
BBACK: call BNOWRITE ; Find the NULL
jr nz,BBACK
BBDONE: ld bc,BUFFER
push bc
BSRCHL: call BNOWRITE ; Is this the end?
BSRCHL2:
call BNOWRITE
jr z,BSRCHNO
call FNOWRITE ; No, Place us properly
BSRCL1: call BNOWRITE
jr nz,BSRCL1
call FNOWRITE
ld c,0
pop de
push de
BSRCHECKING:
inc c
call UCASE
ld b,a
ld a,(de)
ld hl,(POS)
sbc hl,de
jr z,BSRGOTIT
inc de
call UCASE ; Make all upcase
cp b
jr nz,BSRGOTIT ; Same?
push de
push bc
call FNOWRITE
pop bc
pop de
jr BSRCHECKING
BSRGOTIT:
push af
ld b,c
BSR_BACKING_UP:
push bc
call BNOWRITE
pop bc
djnz BSR_BACKING_UP
pop af
jr nz,BSRCHL2
call DELTOEND
xor a
call BESET ; We went back -- Indicate it
cpl
ld de,(POS)
ld (NOOUT+1),a
pop bc
pop hl
pop af
push de
call GETLINE ; Get a whole line in
pop hl
ld (POS),hl
call NOSAV
; xor a ; Getline always ends with a null
ld (NOOUT+1),a
jp SHOWTOEND
BSRCHNO:
pop bc
BSRCHNO1:
call BEEP ; Not found do the beep thing
PUTBACK:
pop hl
pop af
ld (FP),hl ; Restore our pointers
ld (SEC),a
RRAND: ld c,21h
call DORAND ; Read that first one back in
or a
ret z
ZBUF: push de
ld hl,SECBUF ; Zero out our record
ld bc,127
call ZERO
pop de
ret
QUITSH: call qerror ; Pop the shell stack
ret z ; Unless we are an error handler
pop hl
call SHPOP
DONEOUT:
call GOEOLN ; Go to the end and CR
ld a,13
JCOUT: jp COUT
BEEP: ld a,bell
jr JCOUT
BACKLINE: ; Go to previous command line
call OPEN
ld a,(ENDFLG)
or a
call z,EZER ; Till we get to start
BGET: call BNOWRITE
call z,FNOWRITE
jr z,BEEP ; No command line before
ld hl,TBUF
ld (hl),0
inc hl
BINSERT: ; Insert the line backing up
ld (hl),a
inc hl
push hl
call BNOWRITE
pop hl
jr nz,BINSERT
push hl
ld hl,BACKFLG ; Did we just go backwards?
ld a,(hl)
ld (hl),0ffh
or a
pop hl
jr z,BGET
push hl
call DELLN1 ; Kill existing line
pop hl
dec hl
BIN2: ld a,(hl)
dec hl
or a
jr z,GOBEGINOPTION ; Put her there
push hl
call INSERT
pop hl
jr BIN2
GOBEGINOPTION:
push af
ld a,(GOBEGFLG)
or a
call nz,GOBOLN
call NOSAV
pop af
ret
NEXTLINE:
ld a,(ENDFLG) ; Are we at the end?
or a
ret z
call OPEN ; Open the sucker if it ain't already
GETLINE:
FGET: call FNOWRITE
jr z,CHKTOP ; At the end?
push af
call NOTTOP ; Set flag
pop af
ld hl,TBUF
FINSERT:
ld (hl),a
inc hl
push hl
call FNOWRITE ; Bring 'em in
pop hl
jr nz,FINSERT
ld (hl),0
ld hl,BACKFLG ; Did we go back?
ld a,(hl)
ld (hl),0
or a
jr nz,FGET
call DELLN1 ; Delete the line
ld hl,TBUF
FIN2: ld a,(hl)
inc hl
or a
jr z,GOBEGINOPTION
push hl
call INSERT ; Push the chars in
pop hl
jr FIN2
CHKTOP: call DELLN1 ; Clean out existing line
call BNOWRITE
xor a
jr ESET ; Fix End Flag
NOTTOP: xor a
cpl
jr ESET
EZER: xor a ; Set the lot of them
cpl
BESET: ld (BACKFLG),a
ESET: ld (ENDFLG),a
ret
; ---------------------------------------
; Support routines for the commands above
;
SETSCAN:
push af ; Delete line and quiet terminal
call DELLN1
xor a
cpl
ld (NOOUT+1),a
pop af
ret
INSERT: call DOSAV
ld e,a ; Put the char in
ld a,(INSFLG)
or a
jr nz,YAINS
ld hl,(POS)
ld a,(hl)
or a
ld a,e
jr nz,OVERWRITE ; Do we insert?
YAINS: xor a
ld b,a
push de
call MOVEUP ; Push them up
pop de
jp z,BEEP ; No room
ld a,e
OVERWRITE:
ld hl,(POS)
ld (hl),a
call IPOS ; Skip over it (PRINTing it)
jr SHOWTOEND ; Redisplay
DELETE: call DOSAV
ld de,(POS) ; Kill a char quiet-like
ld a,(de)
or a
ret z
push af
ld hl,DELETED
inc (hl)
cp ' '
jr nc,NOINC2 ; Increment DELETED as neccessary
inc (hl)
NOINC2: call MOVEDOWN
pop af
or a
ret
OUTPUT: call crlf ; New line
OUTPUT1:
call PROMPT ; Redisplay prompt
OUTPUT2:
ld hl,BUFFER ; And command line
ld (POS),hl
jp SHOWTOEND
CLRTOEND:
ld hl,(POS) ; Wipe out command line from cursor to right
ld de,0
call DOSAV
CLRLOOP:
ld a,(hl) ; Loop until NULL
or a
jr z,NOWBACK
cp ' '
jr nc,CLR2
inc de
call SPACE ; Two for Control Chars
CLR2: call SPACE ; Overwrite it
inc hl
inc de
jr CLRLOOP
NOWBACK:
ld a,d
or e
ret z
dec de
call BACK ; And return to old location
jr NOWBACK
IPOS: ld hl,(POS) ; Get current char and PRINT it
ld a,(hl)
or a
ret z ; Return zero if NULL
push af
inc hl
ld (POS),hl
push bc
ld b,a
ld a,(NOOUT + 1) ; Silence?
or a
ld a,b
pop bc
call z,CCOUT
pop af
ret
DPOS: ld hl,(POS) ; Back up (^H)
dec hl
ld a,(hl)
or a
ret z
push af
ld (POS),hl
cp ' '
call c,BACK ; Two for Control Char
call BACK
pop af
ret
SHOWTOEND:
call PRINTHL ; Show line to end
jr nz,SHOWLP
ld hl,DELETED ; With spaces for deleted text
ld a,(hl)
or a
jr z,SHOWLP
SHW1: push af
call SPACE
pop af
dec a
jr nz,SHW1
SHW2: call BACK
dec (hl)
jr nz,SHW2
SHOWLP: ld a,d
or e
ret z
dec de
call DPOS
jr SHOWLP
PRINTHL:
ld de,0 ; Show text at HL to NULL
PHLOOP: call IPOS
ret z
inc de
KILLFLG:
ld a,0 ; Check for UNDO
or a
ret nz
push hl
push de
push bc
ld c,11 ; Check for console in
call BDOS
pop bc
pop de
pop hl
or a
jr z,PHLOOP
call cin ; Check for previous input
ld (GETKEY+1),a
cp ' '
jr c,PHLOOP
cp 127 ; If it's an input, don't redisplay
ret nz
jr PHLOOP
GETKEY: ld b,0
xor a
ld (GETKEY+1),a ; Save the previous key
ld a,b
or a
call z,cin
ret
MOVEUP: ld hl,(POS) ; Move the text up to accept new char
ld a,' '
UPLOOP: ld b,(hl)
ld (hl),a
inc hl
ld a,b
or a
jr nz,UPLOOP
ld (hl),a
ld de,BUFFER + 300
sbc hl,de ; Until the end
jr z,MOVEDOWN ; No good, move it back
or 1
ret
MOVEDOWN: ; Move a char out -- Delete
ld hl,(POS)
ld d,h
ld e,l
DNLOOP: inc hl
ld a,(hl) ; Pull them down till we find a NULL
ld (de),a
or a
inc de
jr nz,DNLOOP
ret
UNDO: ld hl,kill ; Insert Kill buffer
xor a
cpl
ld (KILLFLG + 1),a
call undo1
xor a
ld (KILLFLG + 1),a
jp SHOWTOEND
UNDO1: ld a,(hl) ; insert at HL until NULL
inc hl
or a
ret z
push hl
call INSERT
pop hl
jr UNDO1
WFFILE: call RCHECK ; Forward a char in the file with write
ld de,(FP)
ld (de),a
ld hl,SECTOP-1
sbc hl,de
jr nz,FNOWRITE
call WRAND
FNOWRITE: ; Forward a char
call RCHECK
ld de,(FP)
inc de
ld hl,SECTOP
sbc hl,de
jr nz,NOREAD
ld hl,SEC
inc (hl)
call RRAND
ld de,SECBUF
NOREAD: ld a,(de)
ld (FP),de
or a
ret
WBFILE: call RCHECK ; Back a char in file with write
ld de,(FP)
ld (de),a
ld hl,SECBUF
sbc hl,de
jr nz,BNOWRITE
call WRAND
BNOWRITE: ; Back a char
call RCHECK
or a
ld de,(FP)
dec de
ld hl,SECBUF-1
sbc hl,de
jr nz,NOREAD
ld hl,SEC
dec (hl) ; Should never get to be ZERO... Honest.
jr nc,BNOZERO
ld (hl),0 ; But, what the hell, it's free.
BNOZERO:
call RRAND
ld de,SECTOP-1
jr NOREAD
WRAND: ld c,22h ; Write random
call DORAND
or a
ret z
jp nz,WMERR
DORAND: ld a,(SEC) ; Put random record in right place in FCB
ld hl,FCB+33 ; Set the DMA and call BDOS
ld (hl),a
inc hl
xor a
ld (hl),a
inc hl
ld (hl),a
push de
call SETDMA
call FBDOS
pop de
ret
SETDMA: push bc ; Set the DMA to the SECBUF
ld c,1ah
ld de,SECBUF
call BDOS
pop bc
ret
BCD2: push bc ; Format two digit numbers
ld c,0ffh
BCD2A: inc c
sub 10
jr nc,BCD2A ; Put them in BCD (??) form
add a,10
ld b,a
ld a,c
rlca
rlca
rlca
rlca
or b
pop bc
ret
PAFDC: ld d,0 ; PRINT them out
MAFDC: push af ; Put them in a memory location
call BCD2
push af
rra
rra
rra
rra
and 1111b
call nz,DEPUT ; Output tens
pop af
call DEPUT ; Output ones
pop af
ret
DEPUT: and 1111b
add '0'
inc d
dec d ; Check for output
jp z,COUT
ld (de),a ; Else memory stuff
inc de
ret
;
; Bdos console in. With no echo.
;
CIN: push hl
push de
push bc
ld hl,(1)
ld de,9
add hl,de
ld (hl),0C9h
push hl
ld c,1
call BDOS
pop hl
ld (hl),0c3h
pop bc
pop de
pop hl
ret
RCHECK: push af ; Have we read already?
ld a,(RDFLG)
or a
jr nz,RCK1 ; Yes