Files
RomWBW/Source/Images/d_bp/u15/MENU.MAC
2020-01-03 20:42:06 -08:00

1510 lines
30 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;
; PROGRAM: MENU
; AUTHOR: RICHARD CONN
; VERSION: 3.2
; DATE: 10 June 84
; PREVIOUS VERSIONS: 3.1 (28 Mar 84), 3.0 (18 Mar 84)
; DERIVATION. MENU 1.4 for ZCPR2
;
VERS EQU 32
;
; MENU is the ZCPR3 Menu Processor. It loads, looks for the MENU.MNU
; file, and then displays it to the user (optionally) and prompts him for
; a single-character command. The ZCPR3 Multiple Command Line Buffer must
; be installed for MENU to work, and MENU uses this buffer to chain to the
; programs selected by the user and return to itself at the proper place.
;
; MENU supports multiple menus within one MENU.MNU file. When a command
; is invoked, MENU returns to the menu the command came from.
;
; MENU will ONLY RUN on ZCPR3 systems with the Multiple Command Line
; Buffer Option enabled.
;
;
; Menu Constants
;
sysmenu equ 0 ;System Menu Enabled? 0=no, 1=yes
; 1 Special Menu Command Chars
RNM EQU '>' ;NEXT MENU
RNMP EQU '.' ;NEXT MENU PRIME (ALTERNATE)
RLM EQU '<' ;LAST MENU
RLMP EQU ',' ;LAST MENU PRIME (ALTERNATE)
RFM EQU '*' ;FIRST MENU
;
if sysmenu
RSM EQU '$' ;SYSTEM MENU (PASSWORD REQUIRED)
; THIS IS SAME AS CONTROL CHAR
endif ;sysmenu
; 2 Internal Menu Control Chars
MCMD EQU ':' ;COMMAND TO JUMP TO ANOTHER MENU
PCHAR EQU '"' ;INDICATES AUTO PROMPT FOR SPECIFIC CMD
MINDIC EQU '#' ;MENU SECTION INDICATOR
MFIRST EQU '%' ;FIRST MENU INDICATOR
GOPTION EQU '-' ;GLOBAL OPTION INDICATOR
WOPTION EQU '!' ;ACTIVATES WAIT UPON RETURN
; 3 Menu Option Chars
COPTION EQU 'C' ;DISPLAY COMMAND LINE TO USER
DOPTION EQU 'D' ;DISPLAY MENU TO USER
POPTION EQU 'P' ;PAGE OUT MENU DISPLAY TO USER
XOPTION EQU 'X' ;DISABLE ZCPR3 RETURN
; 4 Miscellaneous
IBUFSZ EQU 254 ;SIZE OF INPUT LINE BUFFER
VARFLAG EQU '$' ;VARIABLE FLAG
;(FOLLOWED BY D,U,Fn,Nn,Tn)
CMDSEP EQU ';' ;ZCPR3 COMMAND SEPARATOR
;
; Enter/Exit Standout Mode (Recommended that these values not be changed)
;
DIM EQU 'A'-'@' ; ^A TO ENTER STANDOUT
NOTDIM EQU 'B'-'@' ; ^B TO EXIT STANDOUT
;
; MACRO Library of Definitions
;
MACLIB Z3BASE.LIB
;
; ZCPR3 CONSTANTS
;
wboot equ 0
bentry equ 5
fcb equ 5ch
tbuff equ 80h
BEL equ 7
CR equ 0dh
LF equ 0ah
CTRLC equ 'C'-'@'
TAB equ 'I'-'@'
CTRLZ equ 'Z'-'@'
;
; MACROS TO PROVIDE Z80 EXTENSIONS
; MACROS INCLUDE:
;
; BR - JUMP RELATIVE
; BRC - JUMP RELATIVE IF CARRY
; BRNC - JUMP RELATIVE IF NO CARRY
; BRZ - JUMP RELATIVE IF ZERO
; BRNZ - JUMP RELATIVE IF NO ZERO
; BJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO
; PUTRG - SAVE REGISTERS
; GETRG - RESTORE REGISTERS
;
;
;
; Z80 MACRO EXTENSIONS
;
BR MACRO ?N ;;JUMP RELATIVE
IF I8080 ;;8080/8085
JMP ?N
ELSE ;;Z80
.Z80
JR ?N
.8080
ENDIF ;;I8080
ENDM
;
BRC MACRO ?N ;;JUMP RELATIVE ON CARRY
IF I8080 ;;8080/8085
JC ?N
ELSE ;;Z80
.Z80
JR C,?N
.8080
ENDIF ;;I8080
ENDM
;
BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
IF I8080 ;;8080/8085
JNC ?N
ELSE ;;Z80
.Z80
JR NC,?N
.8080
ENDIF ;;I8080
ENDM
;
BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
IF I8080 ;;8080/8085
JZ ?N
ELSE ;;Z80
.Z80
JR Z,?N
.8080
ENDIF ;;I8080
ENDM
;
BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
IF I8080 ;;8080/8085
JNZ ?N
ELSE ;;Z80
.Z80
JR NZ,?N
.8080
ENDIF ;;I8080
ENDM
;
BJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
IF I8080 ;;8080/8085
DCR B
JNZ ?N
ELSE ;;Z80
.Z80
DJNZ ?N
.8080
ENDIF ;;I8080
ENDM
;
PUTRG MACRO
PUSH H ;;SAVE REGISTERS IN ORDER
PUSH D
PUSH B
ENDM
;
GETRG MACRO
POP B ;;RESTORE REGISTERS IN ORDER
POP D
POP H
ENDM
;
; END OF Z80 MACRO EXTENSIONS
;
;
; Externals from SYSLIB
;
ext z3vinit,cls,stndout,stndend
ext getcl1,putcl,getsh2,qshell,retud,getefcb,shpush,shpop
ext getshm,putshm,moveb,getfn2,pfn1,getcrt,getzrun,putzex,putcst
ext eprint,cin,cout,caps,crlf,pafdc,madc,bline,initfcb,sksp
ext f$open,f$close,f$read,codend,hmovb
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3vinit ;initialize the ZCPR3 Env and the VLIB Env
jmp strt
;
; This is the FCB which defines the default name of the MENU.MNU file
;
if sysmenu
ppass:
db 'SYSTEM ',0 ;system password
endif ;sysmenu
;
menufcb:
db 0 ;FCB for MENU.MNU
db 'MENU '
db 'MNU'
ds 4
scratch: ;this doubles as a scratch area
ds 16 ;buffer definition is at end of program
ds 4 ;36 bytes total
;
; Start of Program
;
strt:
;
; Check for Shell Stack
;
call getsh2 ;get shell status
brnz strt0 ;skip over shell init
call eprint
db ' No Shell Stack',0
ret
;
; See if Command Line Available
;
strt0:
call getcl1 ;get line
brnz strt01
call eprint
db ' No Command Line',0
ret
;
; See if this program was invoked as a shell
;
strt01:
call qshell ;find out from ZCPR3 environment
push psw ;save status
xra a ;A=0
call putcst ;put command status (normal = 0)
pop psw ;restore status
jz menu ;do not push onto stack if invoked as a shell
;
; Set Name of Shell from External FCB if Possible or From Default if Not
;
setshn:
call retud ;get run address
lxi h,shdisk ;pt to shell disk
mov a,b ;get disk
adi 'A' ;convert to letter
mov m,a ;set disk letter
inx h ;pt to user 10's
mov a,c ;get user number
mvi b,10 ;subtract 10's
mvi d,'0' ;set char
setshn1:
sub b ;subtract
brc setshn2
inr d ;increment digit
br setshn1
setshn2:
add b ;get 1's
mov m,d ;set 10's digit for user
inx h ;pt to 1's digit
adi '0' ;compute 1's digit
mov m,a ;set 1's digit
call getefcb ;get ptr to external fcb
brz strt02 ;no external FCB, so use default name
inx h ;pt to program name
lxi d,shname ;pt to string
mvi b,8 ;8 chars
call moveb ;copy into buffer
;
; Check for File Name and Set It If Given
;
strt02:
lxi h,fcb+1 ;pt to file name
lxi d,menufcb+1
mvi b,11 ;11 chars
mov a,m ;get first char
cpi ' '
cnz moveb ;copy if one present
;
; Set File Name in MENUFCB into Line
;
lxi h,menufcb+1 ;set shell file name
lxi d,shfile ;pt to shell file
mvi b,8 ;8 chars
strt03:
mov a,m ;get next char
cpi ' ' ;done?
brz strt04
stax d ;put char
inx d ;pt to next
strt04:
inx h ;pt to next
bjnz strt03
mvi a,'.' ;put dot
stax d
inx d ;pt to next
mvi b,3 ;file type
strt05:
mov a,m ;copy
stax d
inx h ;pt to next
inx d
bjnz strt05
xra a ;store zero
stax d
;
; Set Menu Number
;
mvi b,1 ;shell message 1
xra a ;menu 0
call putshm ;set message
;
; Push Name of Shell onto Stack
;
lxi h,shdisk ;pt to name of shell
call shpush ;push shell onto stack
brnz strt2
;
; Shell Successfully Installed
;
call eprint
db ' Shell Installed',0
ret
;
; Shell Stack Push Error
;
strt2:
cpi 2 ;shell stack full?
brnz strt3
;
; Shell Stack is Full
;
call eprint
db ' Shell Stack Full',0
ret
;
; Shell Stack Entry Size is too small for command line
;
strt3:
call eprint
db ' Shell Stack Entry Size',0
ret
;
; Check for ZEX Execution and Pass ZEX if So
;
menu:
call getzrun ;is ZEX running?
brz runmenu ;process menu if not
br menuz1 ;skip new line
menuzex:
call crlf ;new line
menuz1:
call eprint
db 'Menu> ',0
mvi a,1 ;tell ZEX that it is prompted
call putzex
call codend ;set up buffer
mvi m,ibufsz ;set size
mvi a,0FFH ;capitalize
call bline ;get line from ZEX
xra a ;A=0
call putzex ;resume ZEX normally
call sksp ;skip over leading spaces
mov a,m ;check for comment
cpi ';'
brz menuzex
xchg ;DE pts to command line
xra a ;don't display command
sta cpflag
jmp runcmnd ;run command pted to by DE
;
; Begin Menu Processing
;
runmenu:
call eprint
db 'MENU Version '
db (vers/10)+'0','.',(vers mod 10)+'0',0
;
; Check for Wait Flag and Wait if So
;
mvi b,0 ;get shell message 0
call getshm
ani 80h ;check for wait flag
cnz sak ;Strike Any Key
;
; Open Menu File
;
lxi h,fcb ;copy FCB into MENU FCB
lxi d,menufcb
mvi b,36 ;36 bytes
push d ;save ptr
call moveb
pop d ;pt to MENU.MNU FCB
call initfcb ;init fcb
call f$open ;open file
brz menu1 ;abort if no menu
call eprint
db CR,LF,' File ',0
lxi d,menufcb+1
call pfn1
call eprint
db ' Not Found',0
jmp shpop
;
; Load MENU.MNU from disk
;
menu1:
call codend ;get address of buffer for menu load
mload:
lxi d,menufcb ;pt to FCB
call f$read ;read in next block
ora a ;error?
brnz mloaddn ;load done if error
lxi d,tbuff ;copy from TBUFF into memory pted to by HL
xchg ;HL is source, DE is dest
mvi b,128 ;128 bytes
call hmovb
lhld bentry+1 ;get address of top of TPA
mov a,h ;set to bottom of ZCPR3
sui 10
cmp d ;about to overflow ZCPR3?
brnc mload1 ;continue if not
call eprint
db CR,LF,' TPA Full',0
ret
mload1:
xchg ;HL pts to next byte to load to
br mload ;continue load
;
; Init Flags and Clear MSB of all bytes in Menu File
;
mloaddn:
call f$close ;close input file
mvi m,CTRLZ ;ensure EOF mark
lxi d,80H ;pt to next block
dad d
shld ibuff ;set ptr to input line buffer
mvi m,ibufsz ;set size
dad d ;allow 256 bytes
dad d
shld expline ;set ptr to expand line
xra a ;A=0
sta cflag ;turn off command display
sta dflag ;turn off menu display
sta pflag ;disallow paging
sta cpmok ;turn off ZCPR3 return flag
call codend ;pt to beginning of file
push h ;save ptr
menul1:
mov a,m ;get byte
ani 7FH ;mask out MSB
mov m,a ;put byte
inx h ;pt to next
cpi CTRLZ ;EOF?
brnz menul1 ;continue if not
;
; Mark all Menu Sections
;
pop h ;HL pts to first byte of menu
mvi b,0FFH ;set menu counter
;
; Skip to Next Menu
;
menul2:
mov a,m ;get byte
cpi CTRLZ ;error?
jz mstrerr ;structure error if so
cpi MINDIC ;menu indicator (start of menu?)
brnz menul4
ori 80H ;beginning of menu found -- set MSB
mov m,a ;put byte
inr b ;increment menu count
inx h ;pt to next
mov a,m ;get byte
cpi MINDIC ;menu indicator (end of menu?)
brz menul5 ;done if so
cpi CTRLZ ;error?
jz mstrerr
;
if sysmenu
cpi RSM ;system menu indicator?
brnz menul3
mov a,b ;set system menu number
sta smeno
mvi a,0FFH ;set flag
sta smenfl ;system menu present
dcx h ;back up to beginning of menu
shld smenadr ;start address
inx h ;pt to RSM
endif ;sysmenu
;
; Skip out Menu Display
;
menul3:
call lskipt ;skip to beginning of next line
brz menul4 ;found menu indicator
cpi CTRLZ ;error?
jz mstrerr
br menul3 ;continue if not
;
; Skip to Next Menu
;
menul4:
call lskip ;skip to beginning of next menu
br menul2
;
; Check Menu Options
;
menul5:
call codend ;pt to beginning of file
mov a,m ;check for option
cpi GOPTION ;global option char?
jnz mfile ;if no global option, scan for menu files
inx h ;pt to option char
option:
mov a,m ;get option char
call caps ;capitalize
inx h ;pt to next
cpi CR ;done?
brz optdn
cpi COPTION ;display command?
brz optc
cpi DOPTION ;display menu?
brz optd
cpi POPTION ;paging?
brz optp
cpi XOPTION ;exit OK?
jnz mstrerr ;option error if not
;
; Disable Exit to ZCPR3
;
mvi a,0FFH ;turn flag off
sta cpmok
br option
;
; Process Paging Option
;
optp:
mvi a,0FFH ;set flag
sta pflag
br option
;
; Process Display Menu Option
;
optd:
mvi a,0FFH ;set flag
sta dflag
br option
;
; Process Display Command Option
;
optc:
mvi a,0FFH ;set flag
sta cflag
br option
;
; Option Processing Done
;
optdn:
inx h ;skip LF
;
; Check for Menu Display
;
mfile:
mov a,m ;get first byte
ani 7FH ;mask
cpi MINDIC ;start of menu?
jnz mstrerr
;
; Check and Set First Menu
;
shld mstart ;save start address of first menu item
mvi m,MFIRST+80H ;set first char of first menu
;
; Entry Point for Menu Display
; On entry, HL pts to first byte of current menu
;
dmenu:
mvi b,1 ;shell message 1 contains menu number
call getshm ;get menu number flag
cnz mchc0 ;skip to proper menu
shld cstart ;save start address of current menu
lda cflag ;copy display command flag for temp use
sta cpflag
lda dflag ;copy display menu flag for temp use
sta dpflag
lda pflag ;copy paging flag for temp use
sta ppflag
inx h ;pt to first char after menu indicator char
dispm1:
mov a,m ;get char
call caps ;capitalize
inx h ;pt to next
cpi CR ;end of options?
brz dispm2
;
if sysmenu
cpi RSM ;system menu?
brz dispm1 ;ok if so
endif ;sysmenu
;
cpi COPTION ;command display?
brz dispmc
cpi DOPTION ;display?
brz dispmd
cpi POPTION ;paging?
brz dispmp
cpi XOPTION ;ZCPR3 return?
jnz mstrerr ;error if not
;
; Toggle ZCPR3 Return Option
;
lda cpmok ;get flag
cma ;toggle
sta cpmok
br dispm1
;
; Toggle Paging Option
;
dispmp:
lda ppflag ;get flag
cma ;toggle
sta ppflag
br dispm1
;
; Toggle Display Menu Option
;
dispmd:
lda dpflag ;get flag
cma ;toggle
sta dpflag
br dispm1
;
; Toggle Display Command Option
;
dispmc:
lda cpflag ;get flag
cma ;toggle
sta cpflag
br dispm1
;
; Done with Menu-Specific Option Processing
;
dispm2:
call lskip ;skip to LF
lda dpflag ;display menu?
ora a ;0=no
brz dispm8 ;skip over menu if not
call getnlines ;get line count in A
sta pagcnt ;set count
lda ppflag ;paging?
ora a ;0=no
push psw ;save flag
cnz cls ;clear screen if so
pop psw ;get flag
cz crlf ;else new line
;
; Print Next Line of Menu if not Starting with ESCAPE Char (MINDIC)
;
dispm3:
mov a,m ;get first char of line
ani 7FH ;mask
cpi MINDIC ;done?
brz dispm4
call expand ;expand line pted to by HL
push h ;save ptr to next line
xchg ;HL pts to expanded line
call lprintx ;print line pted to by HL ending in <CR>
pop h ;pt to next line
br dispm3
;
; Done with Menu Display -- Page it out
;
dispm4:
call lskip ;skip to first char of next line (option char)
shld optstrt ;set start address of options
lda pagcnt ;number of remaining lines
mov b,a ;count in B
ora a ;ok?
brz dispm6 ;don't do anything if already there
lda ppflag ;page?
ora a ;0=No
brz dispm6
;
; Page Loop for Menu Display
;
dispm5:
call crlf ;new line
bjnz dispm5
;
; Determine if Another Menu Follows
;
dispm6:
xra a ;A=0
sta nmenfl ;set for no next menu
mov a,m ;ok?
ani 7FH ;mask
cpi CTRLZ ;error if EOF
jz mstrerr
cpi MINDIC ;next menu?
brnz dispm7
inx h ;double indicator if end
mov a,m
cpi MINDIC ;end?
brz dispm9
;
if sysmenu
cpi RSM ;system menu = no next menu
brz dispm9
endif ;sysmenu
;
mvi a,0FFH ;set next menu
sta nmenfl
br dispm9
dispm7:
call lskip ;skip to next line
br dispm6
;
; Skip over current menu so it is not displayed
;
dispm8:
call lskipt ;skip to beginning of command
brnz dispm8
call lskip ;skip over end of display indicator
shld optstrt ;set pointer to options
br dispm6 ;determine if next menu available
dispm9:
;
; Ready for Option Input
; The following Flags/Values are now set:
; CPFLAG -- Display Command Flag (0=No, 0FFH=Yes)
; DPFLAG -- Display Menu Flag (0=No, 0FFH=Yes)
; OPTSTRT -- Address of First Menu Option
; NMENFL -- 0 if no next menu, 0FFH if next menu
; MSTART -- Start Address of MINDIC Before Menu Display
; (MSTART)=MFIRST with MSB Set
prompt:
call stndout ;begin standout
mvi a,0ffh
sta pagcnt ;turn off paging
sta dpflag ;turn on future menu displays
call retud ;get DU
mov a,b ;print D
adi 'A'
call cout
mov a,c ;print U
call pafdc
call eprint
db '> Command (CR=Menu',0
lda cpmok ;OK to return to ZCPR3?
ora a ;0=No
cnz prmptc
lhld cstart ;pt to first char
mov a,m ;get it
ani 7FH ;mask
cpi MFIRST
cnz prmptf ;print previous menu prompt if not first menu
lda nmenfl ;next menu available?
ora a ;0=No
cnz prmptn ;print next menu prompt
call eprint
db ') - ',0
call stndend ;end standout
prompt1:
call cin ;get response
call caps ;capitalize
mov b,a ;result in B
;
; Check for CR
;
cpi CR ;<CR>?
jz dispm2 ;reprint menu if so
;
; Check for Reboot
;
lda cpmok ;ok to abort?
ora a ;0=No
brz prmpt0
mov a,b ;get command
cpi CTRLC ;reboot?
jz shpop ;pop shell stack and return to OS if so
;
; Check for Command to Return to First Menu
;
prmpt0:
mov a,m ;get it
ani 7FH ;mask
cpi MFIRST
brz prmpt1
mov a,b ;get command
cpi RFM ;return to first menu?
brnz prmpt1
lhld mstart ;pt to first menu
mvi b,1 ;shell message 1 is menu number
xra a ;A=0=menu 0
jmp putshm ;reenter shell at first menu
;
; Check for Command to go to Next Menu
;
prmpt1:
lda nmenfl ;next menu available?
ora a ;0=No
brz prmpt2
mov a,b ;get command
cpi RNMP ;goto next menu?
brz rnmx
cpi RNM ;goto next menu?
brnz prmpt2
rnmx:
mvi b,1 ;shell message 1 is menu number
call getshm ;increment menu number
inr a
jmp putshm ;reenter menu system at new menu
;
; Check for Command to go to Last Menu
;
prmpt2:
mov a,m ;get menu char
ani 7FH ;at first menu?
cpi MFIRST
brz prmpt3 ;skip if at first menu
mov a,b ;get command
cpi RLMP ;goto last menu?
brz lstmnu
cpi RLM ;goto last menu?
brnz prmpt3
lstmnu:
mvi b,1 ;shell message 1 is menu number
call getshm ;decrement menu number
dcr a
jmp putshm ;reenter shell at last menu
;
; Check for Command to goto System Menu
;
prmpt3:
if sysmenu
;
lda smenfl ;system menu available?
ora a ;0=No
brz prmpt4
mov a,b ;get command
cpi RSM ;system menu?
brnz prmpt4
call password ;prompt for and get password
jnz prompt ;reprompt if error
lhld smenadr ;get address of system menu
lda smeno ;set system menu number
mvi b,1 ;shell message 1 is menu number
jmp putshm ;reenter shell at system menu
;
endif ;sysmenu
;
; This is where additional functions may be added
;
prmpt4:
;
; Check for Option Letter
;
lhld optstrt ;pt to first option char
prmptx:
mov a,m ;get it
call caps ;capitalize
cpi MINDIC ;at next menu?
brz prmpter
cmp b ;match user selection?
brz prmptd
call lskip ;skip to next line
br prmptx
;
; Invalid Option
;
prmpter:
call eprint
db BEL,0
jmp prompt1
;
; Process Option
;
prmptd:
mov a,b ;output user selection
call cout
mvi b,0 ;shell message 0, bit 7 = wait flag
call getshm
ani 7FH ;set no wait
call putshm
inx h ;pt to first letter of command
mov a,m ;get it
cpi MCMD ;invoke other menu?
jz mchcmd ;menu change command
cpi WOPTION ;turn on wait?
brnz prmptg
mvi b,0 ;shell message 0, bit 7 = wait flag
call getshm
ori 80h ;set wait flag
call putshm ;set shell message
inx h ;skip option char
prmptg:
call expand ;expand line, DE pts to result
;
; Run Command Pted to by DE
;
runcmnd:
call getcl1 ;get address of command buffer
mov b,h ;... in BC also
mov c,l
mvi a,4 ;HL=HL+4 for address of first char
add l
mov l,a
mov a,h
aci 0
mov h,a
mov a,l ;store address
stax b
inx b
mov a,h
stax b
;
; Copy Command Line in DE into Buffer in HL
;
cmdcpy:
ldax d ;get command letter
call caps ;capitalize it
ora a ;done?
brz ccpyd
cpi CR ;done?
brz ccpyd
cpi PCHAR ;prompt?
brz ccpyp
mov m,a ;store it
inx h ;pt to next
inx d
br cmdcpy
ccpyd:
mvi m,0 ;store ending 0
jmp cmddisp ;optionally display command
;
; Prompt User for Input and Accept It
;
ccpyp:
inx d ;pt to first char of prompt
call crlf ;new line
ccpyp1:
ldax d ;get char
cpi PCHAR ;end of prompt?
brz ccpyp2
cpi CR ;new line?
brz ccpyp3
call cout ;echo char
inx d ;pt to next char
br ccpyp1 ;continue looping
ccpyp2:
inx d ;pt to char after closing PCHAR
ccpyp3:
push d ;save ptr to next char
xchg ;DE pts to buffer
mvi a,0FFH ;capitalize input from user
lhld ibuff ;input line buffer
call bline ;get input from user
xchg ;HL pts to buffer, DE pts to user input
cmdlp:
ldax d ;get char from user
ora a ;end of input?
brz cmdlp1 ;store rest of line
mov m,a ;store char
inx h ;pt to next
inx d
br cmdlp
cmdlp1:
pop d ;DE pts to next char, HL pts to buffer
br cmdcpy ;resume copying
;
; Check for Display of Loaded Command and Do So if Set
;
cmddisp:
lda cpflag ;display command?
ora a ;0=No
rz ;return to OS if so to run command
call crlf ;new line
call getcl1 ;pt to first char
mov e,m ;get low-order address
inx h
mov d,m ;get high-order address
xchg ;HL pts to first char
cmdd1:
mov a,m ;get char
cpi CMDSEP ;done if command separator
rz
inx h ;pt to next
call cout ;print char
br cmdd1
;
; Menu Change Command -- Jump to Specified Menu
;
mchcmd:
inx h ;pt to menu number
call eval ;convert to decimal number in A
sta menuno ;save menu number
call mchc0 ;skip to desired menu to check for it
lda menuno ;get menu number
mvi b,1 ;menu number is shell message 1
jmp putshm ;set message and reenter shell
;
; Entry Point if MENU is Reinvoked
;
mchc0:
mov b,a ;menu number in B
inr b ;add 1 for initial offset
lhld mstart ;pt to first menu
mchc1:
dcr b ;count down
rz ;done if found
mchc2:
call lskipt ;skip to next line
brnz mchc2 ;continue if not end of menu display
mchc3:
call lskipt ;skip to next line
brnz mchc3 ;continue if not at end of menu commands
inx h ;end of MENU.MNU?
mov a,m ;yes if double MINDIC
ani 7FH ;mask
cpi MINDIC
brz mchcerr ;error if so
dcx h ;pt to first char
br mchc1 ;continue
;
; Premature End of Menu File
;
mchcerr:
pop psw ;clear stack
jmp mstrerr ;menu structure error
;
; Print Line pted to by HL Ending in <CR>
; Decrement PAGCNT
;
lprintx:
call lprint ;print without <CR>
jmp crlf ;do <CR> <LF>
;
; Print Line Pted to by HL; Decrement PAGCNT
;
lprint:
mvi b,0 ;set tab counter
lprnt0:
mov a,m ;get char
inx h ;pt to next
ani 7FH ;mask MSB
cpi DIM ;goto standout mode?
brz lprnt3
cpi NOTDIM ;end standout mode?
brz lprnt4
cpi TAB ;tabulate?
brz lprnt2
cpi CR ;done?
brz lprnt1
call cout ;print
inr b ;incr tab counter
br lprnt0
lprnt1:
inx h ;pt to first char of next line
lda pagcnt ;count down pages
dcr a
sta pagcnt
rnz
call getnlines ;get line count in A
sta pagcnt
call eprint
db CR,LF,'Pause -',0
br sak1
lprnt2:
mvi a,' ' ;print <SP>
call cout
inr b ;incr tab counter
mov a,b ;done?
ani 7 ;every 8
brnz lprnt2
br lprnt0
lprnt3:
call stndout ;enter standout mode
br lprnt0
lprnt4:
call stndend ;end standout mode
br lprnt0
;
; Strike Any Key Message
;
sak:
mvi b,0 ;clear any pending wait
call getshm
ani 7FH ;mask MSB
call putshm
sak1:
call stndout ;goto standout
call eprint
db ' Strike Any Key - ',0
call stndend ;exit standout
call cin ;get response
call crlf ;new line
ret
;
; Prompt for, input, and check password (only one chance)
; If accepted, return with Zero Flag Set; if not, return with NZ
;
if sysmenu
password:
call eprint
db CR,LF,'Pass? ',0
lhld ibuff ;pt to input line buffer
xra a ;don't capitalize user input
call bline ;get line from user
lxi d,ppass ;pt to system password
pass1:
ldax d ;get sys pass char
cmp m ;ok?
brnz passerr ;error if no match
inx h ;pt to next
inx d
ora a ;end of strings?
brnz pass1
ret ;return with zero set to show match
passerr:
call eprint
db CR,LF,' Password Error',0
call sak1 ;strike any key
call crlf
mvi a,0FFH ;set no zero
ora a
ret
endif ;sysmenu
;
; Skip to Beginning of Next Line and Test First Char for Menu Indicator
;
lskipt:
call lskip ;skip
mov a,m ;get char
ani 7FH ;mask
cpi MINDIC ;test
ret
;
; Skip to Beginning of Next Line
;
lskip:
mov a,m ;get char
ani 7FH ;mask out MSB
inx h ;pt to next
cpi LF
brnz lskip
ret
;
; Print ZCPR3 Return Prompt
;
prmptc:
call eprint
db ', ^C=Z3',0
ret
;
; Print First/Last Menu Chars
;
prmptf:
call eprint
db ', ',RFM,'=1st Menu, ',RLM,'=Prev Menu',0
ret
;
; Print next menu message
;
prmptn:
call eprint
db ', ',RNM,'=Next Menu',0
ret
;
; Menu Structure Error -- FATAL
; This message is printed to indicate an error in the structure of
; the MENU.MNU file.
;
mstrerr:
call eprint
db CR,LF,' Structure Error',0
jmp shpop
;
; Expand Line Pted to by HL into Scratch Area
; Return with HL pting to next line, DE pting to current line
;
expand:
xchg
lhld expline ;pt to buffer
xchg
exp1:
mov a,m ;get next char
ani 7fh ;mask MSB
stax d ;store char
cpi CR ;end of line?
jz expx
inx h ;pt to next
inx d
cpi VARFLAG ;variable follows?
brnz exp1
;
; Variable Identified - Process it
;
mov a,m ;get next char
inx h ;pt to next
cpi VARFLAG ;one variable char?
brz exp1 ;resume if double VARFLAG
dcx d ;pt to variable position
call caps ;capitalize variable
cpi 'D' ;current disk?
brz expdisk
cpi 'U' ;current user?
brz expuser
cpi 'F' ;filename.typ?
brz expfile
cpi 'N' ;filename?
brz expname
cpi 'T' ;filetype?
brz exptype
br exp1 ;resume expansion
;
; Expand Exit
;
expx:
inx h ;pt to line feed
mov a,m ;get it
cpi LF ;line feed?
brnz expx1
inx h ;pt to char after line feed
expx1:
xchg ;DE pts to next line
lhld expline ;pt to expanded line
xchg ;HL pts to next line, DE pts to expanded line
ret
;
; Expand Disk
;
expdisk:
call retud ;get disk in B
mov a,b ;get disk number (A=0)
adi 'A' ;convert to ASCII
stax d ;store letter
inx d ;pt to next
br exp1 ;resume expansion
;
; Expand User
;
expuser:
call retud ;get user in C
mov a,c ;get user number
mvi b,10 ;subtract 10's
mvi c,'0' ;set char
expu1:
sub b ;-10
brc expu2
inr c ;increment digit
br expu1
expu2:
add b ;+10
adi '0' ;convert 1's to ASCII
mov b,a ;B=1's
mov a,c ;get 10's
stax d ;store 10's
inx d
mov a,b ;get 1's
stax d ;store 1's
inx d ;pt to next
br exp1 ;resume
;
; Expand File
;
expfile:
call getfnum ;get file number
jz exp1 ;resume if error
push h ;save ptr to next char
call ptfn ;set ptr to file name
call putn ;put file name
mvi a,'.'
stax d ;store dot
inx d ;pt to next
call putt ;put file type
pop h ;restore ptr
jmp exp1 ;resume
;
; Expand Name
;
expname:
call getfnum ;get file number
jz exp1 ;resume if error
push h ;save ptr to next char
call ptfn ;set ptr to file name
call putn ;put file name
pop h ;restore ptr
jmp exp1 ;resume
;
; Expand Type
;
exptype:
call getfnum ;get file number
jz exp1 ;resume if error
push h ;save ptr to next char
call ptfn ;set ptr to file name
mvi a,8 ;add 8
add l
mov l,a
mov a,h
aci 0
mov h,a
call putt ;put file type
pop h
jmp exp1 ;resume
;
; Pt to File Name whose Number (1-4) is in A
;
ptfn:
mov b,a ;get number in B
call getfn2 ;pt to file name 2
push d ;save DE
mov a,b ;file 0?
ora a
brz ptfnx
lxi d,11 ;size of file name and type
ptfn1:
dad d ;pt to next
bjnz ptfn1
ptfnx:
pop d ;restore DE
ret
;
; Put File Name pted to by HL
;
putn:
mvi b,8 ;8 chars
br putc
;
; Put File Type pted to by HL
;
putt:
mvi b,3 ;3 chars
;
; Copy Chars from HL to DE for up to B bytes -- flush if space
;
putc:
mov a,m ;get next char
cpi ' ' ;skip spaces
brz putc1
stax d ;put next char
inx d ;pt to next
putc1:
inx h ;pt to next
bjnz putc
ret
;
; Get File Number (1 to 4)
; If valid number, return with value in A and HL pting to next char
; If not valid, return with Z and HL pting to last char (F, N, T)
;
getfnum:
mov a,m ;get char
sui '1' ;convert
brc getfne ;error
cpi 4 ;range?
brnc getfne
inx h ;pt to next char
ret ;NZ from CPI 4
getfne:
dcx h ;error return
xra a
ret
;
; Return Number of Lines on CRT in A
;
getnlines:
push h ;save HL
call getcrt ;get CRT info
inx h ;pt to number of lines
mov a,m ;get count
pop h ;restore HL
dcr a ;subtract 1 for footer
ret
;
; Convert char string pted to by HL into decimal number in A
; On Entry, HL pts to first digit char
; On Exit, HL pts to after last digit char and A=number
;
eval:
push b ;save BC
mvi b,0 ;set value
eval1:
mov a,m ;get digit
sui '0' ;convert to binary
brc eval2
cpi 10 ;range?
brnc eval2
inx h ;pt to next digit
mov c,a ;new digit in C
mov a,b ;multiply B by 10
add a ;*2
add a ;*4
add b ;*5
add a ;*10
add c ;add in new digit
mov b,a ;result in B
br eval1
eval2:
mov a,b ;result in A
pop b ;restore ptr
ret
;
; These buffers overlay the scratch area to save space
;
optstrt equ scratch ;Address of First Option in Current Menu
mstart equ optstrt+2 ;Address of First Menu
cstart equ mstart+2 ;Address of Current Menu
smenfl equ cstart+2 ;System Menu Available Flag (0=No)
smeno equ smenfl+1 ;System Menu Number
smenadr equ smeno+1 ;Address of First Byte of System Menu
nmenfl equ smenadr+2 ;Next Menu Available Flag (0=No)
menuno equ nmenfl+1 ;Number of Menu
pagcnt equ menuno+1 ;Paging Counter
cflag equ pagcnt+1 ;Display Command Line Flag
dflag equ cflag+1 ;Display Menu Flag
pflag equ dflag+1 ;Paging Flag
;
; Buffers
;
ibuff:
ds 2 ;input line buffer
expline:
ds 2 ;scratch area to expand lines in
cpflag:
ds 1 ;Temp Display Command Line Flag
dpflag:
ds 1 ;Temp Display Menu Flag
ppflag:
ds 1 ;Temp Paging Flag
cpmok:
ds 1 ;OK to Return to ZCPR3 (0=No)
tnum:
ds 41 ;space for chars and ending 0
shdisk:
db 'A' ;disk to return to
db '00' ;user to return to
db ':;' ;log in and next command
shname:
db 'MENU ' ;program name (filled in at installation)
shfile:
ds 13 ;file name (12) and ending 0
end