mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2655 lines
52 KiB
2655 lines
52 KiB
; PROGRAM: VMENU
|
|
; VERSION: 1.0
|
|
; DATE: 26 June 84
|
|
; AUTHOR: Richard Conn
|
|
; PREVIOUS VERSIONS: None
|
|
;
|
|
z3env equ 0f400h
|
|
VERS EQU 10 ;version number
|
|
|
|
; VMENU is copyright (c) 1984 by Richard Conn
|
|
; All Rights Reserved
|
|
; VMENU may be used freely by the ZCPR3 Community
|
|
|
|
; VMENU is a screen-oriented, ZCPR3-specific file utility. It can not be
|
|
; installed to run under conventional CP/M. VMENU
|
|
; extensively employs cursor addressing to position a pointer on the
|
|
; screen, allow the user to manipulate the pointer (up, down, right, left,
|
|
; next screen, previous screen, GOTO file). The pointer points to files
|
|
; in the current user directory and displays the user's position dynamically
|
|
; on the screen. Once pointing to a file, user commands can be used to
|
|
; manipulate the file according to options presented in the menu displayed to
|
|
; the user. MENU and VMENU are compatible. In the way of being ZCPR3-
|
|
; specific, VMENU can chain to external programs via the Command Line Buffer
|
|
; and then return, and it recognizes Named Directories (so the user can log
|
|
; into B:, B4:, and MYDIR:, for example).
|
|
|
|
; VMENU is installed by Z3INS.
|
|
|
|
; VMENU works with ZCPR3 only, with 32k or more of RAM.
|
|
|
|
; VMENU can be assembled for use with a Z80 or 8080 microprocessor.
|
|
|
|
;
|
|
; SYSLIB, Z3LIB, and VLIB References
|
|
;
|
|
ext z3vinit,cls,gotoxy,ereol,vprint,envptr,stndout,stndend
|
|
ext pafdc,dutdir
|
|
ext qshell,getefcb,shpush,shpop,getcrt,getfn2,zprsfn
|
|
ext putshm,getshm,getsh,getzrun,getcl1,putzex,putcst
|
|
ext cin,cout,caps,crlf,bline,sksp
|
|
ext f$open,f$read,f$close,initfcb
|
|
ext retud
|
|
ext codend
|
|
|
|
;
|
|
; Basic Definitions
|
|
;
|
|
TRUE EQU 0FFH ;define true and..
|
|
FALSE EQU 0 ;..false.
|
|
;
|
|
DIM EQU 1 ;GOTO DIM
|
|
BRIGHT EQU 2 ;GOTO BRIGHT
|
|
ELTSIZ EQU 11 ;size of file name and type element
|
|
|
|
;
|
|
; User-Customized Definition
|
|
;
|
|
VMNAME MACRO ;;Name of VMENU
|
|
DB 'VMENU'
|
|
ENDM
|
|
VMNFILL MACRO ;;Spaces to fill out name to 8 chars
|
|
DB ' '
|
|
ENDM
|
|
;
|
|
Z80 EQU TRUE ;TRUE to use Z80 Instructions
|
|
WARMBOOT EQU FALSE ;set TRUE to warmboot on exit
|
|
EPS EQU 4*4 ;N lines x 4 cols per screen
|
|
; EPS = Entries Per Screen
|
|
|
|
;
|
|
; Command Line Builder Constants
|
|
;
|
|
FPESC EQU '%' ;escape char
|
|
FPDISK EQU 'D' ;disk only (D)
|
|
FPUSER EQU 'U' ;user only (U)
|
|
FPFILE EQU 'F' ;filename.typ
|
|
FPNAME EQU 'N' ;file name only
|
|
FPTYPE EQU 'T' ;file type only
|
|
FPPTR EQU 'P' ;file entry being pointed to
|
|
MNOTE EQU '#' ;denotes comment area in macro file
|
|
UIN1 EQU 27H ;single quote for user input
|
|
UIN2 EQU 22H ;double quote for user input
|
|
|
|
;
|
|
; Menu Constants
|
|
;
|
|
|
|
; 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
|
|
|
|
; 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
|
|
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
|
|
|
|
;
|
|
; Cursor Positioning Addresses
|
|
;
|
|
EPSLINE EQU (EPS/4)+3 ;position of last line of EPS + 1
|
|
BANADR EQU 1*256+24 ;banner address
|
|
CURHOME EQU 3*256+1 ;home address of cursor
|
|
BOTADR EQU 23*256+1 ;bottom of screen
|
|
CPMADR EQU 22*256+1 ;command prompt message
|
|
CPADR EQU CPMADR+27 ;command prompt address (cursor position)
|
|
ERADR EQU CPMADR+256+15 ;error message
|
|
FNADR EQU 1*256+62 ;address of current file name
|
|
MOREADR EQU FNADR+1*256 ;address of more files message
|
|
DUADR EQU 1*256+4 ;address of current DU
|
|
|
|
;
|
|
; System Functions
|
|
;
|
|
RDCON EQU 1
|
|
WRCON EQU 2
|
|
PUNCH EQU 4
|
|
LIST EQU 5
|
|
DIRCON EQU 6
|
|
RDBUF EQU 10
|
|
CONST EQU 11
|
|
LOGIN EQU 14
|
|
OPEN EQU 15
|
|
CLOSE EQU 16
|
|
SRCHF EQU 17
|
|
SRCHN EQU 18
|
|
ERASE EQU 19
|
|
READ EQU 20
|
|
WRITE EQU 21
|
|
MAKE EQU 22
|
|
REN EQU 23
|
|
INQDISK EQU 25
|
|
SETDMA EQU 26
|
|
INQALC EQU 27
|
|
ATTR EQU 30
|
|
GETPARM EQU 31
|
|
SGUSER EQU 32
|
|
COMPSZ EQU 35
|
|
|
|
;
|
|
; System Addresses
|
|
;
|
|
OS$BASE EQU 000H ;system base..
|
|
CCP EQU 800H ;..and 'ccp' length in bytes.
|
|
GET EQU 0FFH ;get user area e-reg value
|
|
BDOS EQU OS$BASE+05H
|
|
FCB EQU OS$BASE+5CH
|
|
FCBEXT EQU FCB+12
|
|
FCBRNO EQU FCB+32
|
|
FCB2 EQU OS$BASE+6CH
|
|
TBUFF EQU OS$BASE+80H
|
|
TPA EQU OS$BASE+100H
|
|
|
|
;
|
|
; ASCII Definitions
|
|
;
|
|
CTRLC EQU 'C'-'@' ;..control-C..
|
|
CTRLD EQU 'D'-'@'
|
|
CTRLE EQU 'E'-'@'
|
|
CTRLR EQU 'R'-'@'
|
|
CTRLS EQU 'S'-'@' ;..XOFF..
|
|
CTRLX EQU 'X'-'@'
|
|
BEL EQU 07H ;..bell..
|
|
BS EQU 08H ;..backspace..
|
|
TAB EQU 09H ;..tab..
|
|
LF EQU 0AH ;..linefeed..
|
|
FF EQU 0CH ;..formfeed..
|
|
CR EQU 0DH ;..carriage return..
|
|
CAN EQU 18H ;..cancel..
|
|
EOFCHAR EQU 1AH ;..end-of-file..
|
|
CTRLZ EQU 1AH ;..clear screen..
|
|
ESC EQU 1BH ;..and escape character.
|
|
|
|
;
|
|
; 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
|
|
;
|
|
BR MACRO ?N ;;JUMP RELATIVE
|
|
IF Z80
|
|
.z80
|
|
jr ?N
|
|
.8080
|
|
ELSE
|
|
jmp ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
BRC MACRO ?N ;;JUMP RELATIVE ON CARRY
|
|
IF Z80
|
|
.z80
|
|
jr c,?N
|
|
.8080
|
|
ELSE
|
|
jc ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
|
|
IF Z80
|
|
.z80
|
|
jr nc,?N
|
|
.8080
|
|
ELSE
|
|
jnc ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
|
|
IF Z80
|
|
.z80
|
|
jr z,?N
|
|
.8080
|
|
ELSE
|
|
jz ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
|
|
IF Z80
|
|
.z80
|
|
jr nz,?N
|
|
.8080
|
|
ELSE
|
|
jnz ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
BJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
|
|
IF Z80
|
|
.z80
|
|
djnz ?N
|
|
.8080
|
|
ELSE
|
|
dcr b
|
|
jnz ?N
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
; END OF Z80 MACRO EXTENSIONS
|
|
;
|
|
|
|
;
|
|
; 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 Z3BASE.LIB
|
|
MACLIB SYSENV.LIB
|
|
z3eadr:
|
|
jmp start
|
|
SYSENV
|
|
start:
|
|
lxi h,z3eadr ;pt to ZCPR3 environment
|
|
endif
|
|
|
|
;
|
|
; Start of Program -- Initialize ZCPR3 Environment
|
|
; Once Environment is Initialized, One of Three Major Functions
|
|
; will be Performed:
|
|
; 1. VMENU will be installed as a Shell if invoked explicitly
|
|
; by user command
|
|
; 2. The VMENU Function will be performed if VMENU is invoked
|
|
; by ZCPR3 as a Shell and ZEX is not Running
|
|
; 3. A Command Line will be Input by VMENU from ZEX and Passed
|
|
; on to ZCPR3 without Processing
|
|
;
|
|
call z3vinit ;initialize the ZCPR3 Env and the VLIB Env
|
|
;
|
|
; Set Opsys Stack Pointer
|
|
;
|
|
if not WARMBOOT
|
|
lxi h,0 ;clear hl-pair then..
|
|
dad sp ;..add stack address.
|
|
shld stack
|
|
endif ;not warmboot
|
|
|
|
;
|
|
; Check to see if VMENU was executed as a shell
|
|
;
|
|
call qshell ;get and test message from ZCPR3
|
|
jz runsh ;execute shell procedures
|
|
;
|
|
; Initialize VMENU as a Shell
|
|
;
|
|
call shtest1 ;there must be a shell stack
|
|
call shtest2 ;there must be a command line buffer
|
|
;
|
|
; FUNCTION 1: Set Up VMENU as a Shell
|
|
; Run Shell Via Exit to Opsys
|
|
;
|
|
call getefcb ;determine name of program
|
|
brz shgo1 ;name not given, so use default
|
|
inx h ;pt to name
|
|
lxi d,filercmd ;define name of program
|
|
mvi b,8
|
|
call moveb ;copy name
|
|
shgo1:
|
|
lxi h,filercmd ;establish shell
|
|
call shpush ;push onto shell stack
|
|
brnz shgo2 ;error?
|
|
;
|
|
; Establish File Selection
|
|
; 3rd System File = Name of Menu File (2nd token)
|
|
; 4th System File = Name of AFN to Select Files (1st token)
|
|
;
|
|
call getfn2 ;setup file name
|
|
lxi d,11 ;use 2nd system file
|
|
dad d
|
|
xchg ;destination in DE
|
|
lxi h,joker ;pt to joker
|
|
mvi b,11 ;copy joker into 2nd system file
|
|
call move ;... so selection is on joker
|
|
xchg ;HL now pts to 3rd system file
|
|
push h ;save ptr to name of Menu File
|
|
lxi d,fcb2+1 ;pt to FCB
|
|
xchg
|
|
mvi b,11 ;copy 11 chars
|
|
call move
|
|
push d ;save ptr to file spec
|
|
lxi h,fcb+1 ;pt to FCB (use 4th system file name)
|
|
mvi b,11 ;copy 11 chars
|
|
call move
|
|
pop d ;get ptr to file spec
|
|
lxi h,joker ;make wild if none
|
|
mvi b,11 ;11 chars
|
|
ldax d ;get first char
|
|
cpi ' ' ;wild if space
|
|
cz moveb ;copy
|
|
ldax d
|
|
cpi '/' ;wild if option
|
|
cz moveb
|
|
pop d ;get ptr to name of menu file
|
|
lxi h,menufile ;pt to menu file name (default)
|
|
ldax d ;check for no file name given
|
|
mvi b,11 ;11 chars
|
|
cpi ' ' ;if none, set default
|
|
cz moveb
|
|
lxi b,8 ;check file type
|
|
dad b
|
|
xchg
|
|
dad b
|
|
xchg
|
|
ldax d ;check for file type
|
|
mvi b,3 ;3 chars
|
|
cpi ' ' ;if none, set default
|
|
cz move
|
|
;
|
|
; Print Done Message
|
|
;
|
|
simsg:
|
|
mvi a,0 ;default to menu 0
|
|
mvi b,1 ;shell message 1 contains menu number
|
|
call putshm
|
|
;
|
|
mvi b,0 ;shell message 0
|
|
mvi a,0 ;no wait
|
|
call putshm ;set shell message
|
|
;
|
|
call vprint
|
|
db ' Shell Installed',0
|
|
;
|
|
jmp os$ccp1 ;return to opsys
|
|
;
|
|
; Error in Shell Stack Installation
|
|
;
|
|
shgo2:
|
|
cpi 2 ;shell stack full
|
|
brnz shgo3
|
|
call vprint
|
|
db ' Shell Stack Full',0
|
|
ret
|
|
shgo3:
|
|
call vprint
|
|
db ' Shell Entry Size',0
|
|
ret
|
|
|
|
;
|
|
; VMENU was invoked as a Shell
|
|
; Check for ZEX Input in Progress
|
|
;
|
|
runsh:
|
|
call getzrun ;check ZEX message byte
|
|
jnz zexrun ;process ZEX command line if ZEX running
|
|
;
|
|
; Check for Delay Before Resuming VMENU and Delay if Set
|
|
;
|
|
mvi b,0
|
|
call getshm ;get shell message 0
|
|
ani 80h ;check MSB
|
|
cnz sak ;pause for input
|
|
mvi a,0 ;set normal command status
|
|
call putcst
|
|
;
|
|
; FUNCTION 2: Run VMENU and Perform Main Function
|
|
;
|
|
call setup ;init buffers and pointers
|
|
call stackset ;setup stack
|
|
;
|
|
; Begin VMENU Processing
|
|
;
|
|
runsh2:
|
|
call stackset ;reset stack
|
|
call fileload ;load files
|
|
call setscr ;set up screen display variables
|
|
call findcfile ;locate current file
|
|
call menuload ;load menu file
|
|
;
|
|
; Entry Point for Command Processing
|
|
; Display Screen and Input/Process Command
|
|
;
|
|
runsh3:
|
|
call stackset ;reset stack
|
|
call refresh ;refresh screen display
|
|
;
|
|
; Display Current File and Input/Process Command
|
|
;
|
|
loopfn:
|
|
call prcfn1 ;print current file name
|
|
;
|
|
; Input/Process Command
|
|
;
|
|
loop:
|
|
call stackset ;reset stack
|
|
call prompt ;get command from user
|
|
call cmdproc ;process command in A
|
|
call icmsg ;print invalid command msg
|
|
br loop ;continue
|
|
;
|
|
; Set Stack Pointer
|
|
;
|
|
stackset:
|
|
pop d ;get return address
|
|
lhld ibuf ;top of stack
|
|
sphl ;start local stack
|
|
push d ;return address on new stack
|
|
ret
|
|
;
|
|
; Check for Presence of Shell Stack
|
|
;
|
|
shtest1:
|
|
call getsh ;get shell stack data
|
|
rnz
|
|
pop psw ;clear stack
|
|
call vprint
|
|
db 'No Shell Stack',0
|
|
ret
|
|
|
|
;
|
|
; Check for Command Line
|
|
;
|
|
shtest2:
|
|
call getcl1 ;get command line data
|
|
rnz
|
|
pop psw ;clear stack
|
|
call vprint
|
|
db 'No Cmd Line',0
|
|
ret
|
|
|
|
;
|
|
; FUNCTION 3: Run ZEX on Top of VMENU
|
|
; Accept Command Line and Pass it to ZCPR3
|
|
;
|
|
zexrun:
|
|
call vprint ;print prompt
|
|
db 'VMENU> ',0
|
|
mvi a,1 ;tell ZEX that it is prompted
|
|
call putzex
|
|
call getcl1 ;pt to command line buffer
|
|
mov a,l ;set ptr to first char
|
|
adi 4
|
|
mov c,a
|
|
mov a,h
|
|
aci 0
|
|
mov b,a ;BC pts to first char
|
|
mov m,c ;store low
|
|
inx h
|
|
mov m,b ;store high
|
|
inx h ;pt to char count
|
|
xchg ;... in DE
|
|
mvi c,rdbuf ;input line via BDOS
|
|
push d ;save ptr
|
|
call bdos
|
|
pop h ;pt to char count
|
|
inx h
|
|
mov e,m ;get char count
|
|
inx h ;pt to first char
|
|
push h ;save ptr
|
|
mvi d,0 ;DE=char count
|
|
dad d
|
|
xra a ;A=0
|
|
mov m,a ;store ending 0
|
|
pop h ;pt to first char
|
|
call sksp ;skip to first non-blank character
|
|
mov a,m ;get it
|
|
cpi ';' ;comment line?
|
|
jz zexrun1 ;process comment line
|
|
call putzex ;resume ZEX (A=0)
|
|
call putcst ;set command status to normal (A=0)
|
|
ret ;return to opsys
|
|
zexrun1:
|
|
call crlf ;new line
|
|
jmp zexrun
|
|
|
|
;
|
|
;**************************************************
|
|
;
|
|
; CRT Routine for VMENU
|
|
;
|
|
VCLS:
|
|
CALL CLS ;try to clear the screen
|
|
RNZ ;OK if done
|
|
PUSH H ;save regs
|
|
PUSH B
|
|
CALL GETCRT ;get CRT Data
|
|
INX H ;get number of lines on screen
|
|
MOV B,M ;B=number of lines
|
|
VCLS1:
|
|
CALL CRLF ;new line
|
|
BJNZ VCLS1
|
|
POP B ;restore regs
|
|
POP H
|
|
RET
|
|
;
|
|
; EREOL Routine for VMENU
|
|
;
|
|
VEREOL:
|
|
CALL EREOL ;try to erase to EOL
|
|
RNZ ;OK if done
|
|
PUSH B ;save count
|
|
MVI A,' ' ;space out
|
|
CALL VEREOL1 ;send B spaces
|
|
POP B ;get count
|
|
MVI A,BS ;backspace in
|
|
VEREOL1:
|
|
CALL COUT ;send char
|
|
BJNZ VEREOL1 ;count down
|
|
RET
|
|
;
|
|
; Setup Screen Display Variables
|
|
;
|
|
SETSCR:
|
|
LXI H,CURHOME ;set cursor home
|
|
SHLD CURAT
|
|
LHLD RING ;set ring position
|
|
CALL SETMORE ;set more flag if more files on screen
|
|
;
|
|
; Entry to Reset Ring Position at HL
|
|
;
|
|
SETSCR1:
|
|
SHLD RINGPOS ;set current file to first file in ring
|
|
;
|
|
; Entry to Reset Local Ring Position at HL
|
|
;
|
|
SETSCR2:
|
|
SHLD LOCBEG ;front of ring
|
|
LXI D,EPS*ELTSIZ ;new end?
|
|
DAD D
|
|
XCHG
|
|
LHLD RINGEND ;end of ring
|
|
XCHG
|
|
CALL CMPDEHL
|
|
BRC SETSCR3
|
|
XCHG
|
|
SETSCR3:
|
|
XCHG
|
|
SHLD LOCEND
|
|
RET
|
|
|
|
;
|
|
; Set More Flag - Count Files on Screen and See if Display Exceeded
|
|
;
|
|
SETMORE:
|
|
PUSH H ;SAVE REGS
|
|
PUSH D
|
|
PUSH B
|
|
XRA A ;CLEAR FLAG
|
|
STA MORE
|
|
MVI B,EPS ;COUNT DOWN
|
|
LXI D,ELTSIZ ;SIZE OF ELEMENT
|
|
SETMORE1:
|
|
MOV A,M ;GET CHAR
|
|
ORA A ;DONE IF ZERO
|
|
JZ SETMDONE
|
|
DAD D ;PT TO NEXT
|
|
DCR B ;COUNT DOWN
|
|
JNZ SETMORE1
|
|
MOV A,M ;GET CHAR
|
|
ORA A ;DONE IF ZERO
|
|
JZ SETMDONE
|
|
MVI A,0FFH ;SET FLAG
|
|
STA MORE
|
|
SETMDONE:
|
|
POP B ;RESTORE REGS
|
|
POP D
|
|
POP H
|
|
RET
|
|
|
|
;
|
|
; Search for Current File starting at position in HL
|
|
;
|
|
FINDCFILE:
|
|
CALL GETFN2 ;get ptr to current file
|
|
LXI D,11
|
|
DAD D ;... which is 2nd System File
|
|
XCHG ;... ptr in DE
|
|
;
|
|
; Next group of EPS files for file display
|
|
;
|
|
FINDCF1:
|
|
LXI H,CURHOME ;set cursor
|
|
SHLD CURAT
|
|
LHLD LOCBEG ;pt to first file in list
|
|
MVI B,EPS ;number of files in display
|
|
;
|
|
; Check current file
|
|
;
|
|
FINDCF2:
|
|
SHLD RINGPOS ;set position of current ring element
|
|
;
|
|
; Check for end of file ring
|
|
;
|
|
MOV A,M ;end of list?
|
|
ORA A ;done if so
|
|
BRZ FINDCF4
|
|
;
|
|
; Compare candidate file against file in ring
|
|
;
|
|
PUSH H ;save ptr to file
|
|
PUSH D ;save ptr to System File
|
|
PUSH B ;save count
|
|
MVI B,ELTSIZ ;compare
|
|
CALL CMPSTR
|
|
POP B ;get count
|
|
POP D ;get ptr to System File
|
|
POP H ;get ptr to file
|
|
BRZ FINDCF5 ;we found it
|
|
BRC FINDCF5 ;we found following file
|
|
;
|
|
; Advance to next file in ring
|
|
;
|
|
PUSH B ;save count
|
|
LXI B,ELTSIZ ;pt to next element
|
|
DAD B
|
|
;
|
|
; Advance to next file on screen
|
|
;
|
|
PUSH H
|
|
LHLD CURAT ;get cursor position
|
|
MOV A,L
|
|
ADI 19 ;advance cursor
|
|
MOV L,A
|
|
CPI 70
|
|
BRC FINDCF3
|
|
MOV A,H ;get current line
|
|
LXI H,CURHOME ;get home row
|
|
MOV H,A ;set current line
|
|
INR H ;next line
|
|
FINDCF3:
|
|
SHLD CURAT ;set cursor
|
|
POP H
|
|
POP B ;get count
|
|
;
|
|
; Count down files in current display
|
|
;
|
|
BJNZ FINDCF2 ;count down
|
|
MOV A,M ;any following elements in ring?
|
|
ORA A ;0=no
|
|
BRZ FINDCF4
|
|
;
|
|
; End of current display - set new display
|
|
;
|
|
SHLD LOCBEG ;new local beginning
|
|
BR FINDCF1 ;continue search
|
|
;
|
|
; File beyond end of file display - set pointers to first file
|
|
;
|
|
FINDCF4:
|
|
LXI H,CURHOME ;set cursor to first file
|
|
SHLD CURAT
|
|
LHLD RING ;pt to first file
|
|
SHLD RINGPOS
|
|
SHLD LOCBEG ;set local beginning
|
|
;
|
|
; Done - Set Local Ring
|
|
;
|
|
FINDCF5:
|
|
LHLD LOCBEG ;pt to local ring
|
|
JMP SETSCR2
|
|
|
|
;
|
|
; Display file name of current file
|
|
; Side Effect: Change Name of 2nd System File to Current File
|
|
;
|
|
PRCFN1:
|
|
LXI H,FNADR ;position cursor for file name print
|
|
CALL GOTOXY
|
|
CALL GETFN2 ;pt to system file name
|
|
LXI D,11 ;pt to 2nd System File Name
|
|
DAD D
|
|
XCHG ;... in DE
|
|
LHLD RINGPOS ;pt to current file name
|
|
MVI B,11 ;copy into 2nd System File Name
|
|
CALL MOVEB
|
|
JMP PRFN ;print file name
|
|
;
|
|
; Process Command
|
|
;
|
|
ICMSG:
|
|
CALL ERMSG
|
|
DB 'Invld Cmd: ',0
|
|
MOV A,B ;get char
|
|
CPI ' ' ;expand if less than space
|
|
JNC COUT
|
|
MVI A,'^' ;control
|
|
CALL COUT
|
|
MOV A,B ;get byte
|
|
ADI '@' ;convert to letter
|
|
JMP COUT ;return for loop processing
|
|
|
|
;
|
|
; SET UP BUFFERS
|
|
;
|
|
SETUP:
|
|
CALL RETUD ;get home DU
|
|
MOV A,B
|
|
STA H$DR ;home drive
|
|
MOV A,C
|
|
STA H$U$A ;home user area
|
|
CALL CODEND ;start of free space
|
|
LXI D,256 ;256 bytes/unit
|
|
DAD D
|
|
SHLD IBUF ;input line buffer and top of stack
|
|
MVI M,IBUFSZ ;number of bytes in line
|
|
DAD D
|
|
SHLD EXPLINE ;expansion line
|
|
DAD D
|
|
SHLD MENUFCB ;dummy FCB
|
|
DAD D ;next page
|
|
SHLD BUFFER ;free space to end of TPA
|
|
|
|
;
|
|
; Begin Further Inits
|
|
;
|
|
LHLD ENVPTR ;pt to ZCPR3 Env Desc
|
|
LXI D,80H+10H ;pt to cursor commands
|
|
DAD D
|
|
LXI D,CTABLE ;pt to area
|
|
MVI B,4 ;4 commands
|
|
CURINIT:
|
|
MOV A,M ;get command
|
|
STAX D ;put it
|
|
INX H ;pt to next
|
|
INX D
|
|
INX D
|
|
INX D
|
|
BJNZ CURINIT
|
|
;
|
|
LHLD BUFFER ;base address
|
|
SHLD RING ;beginning of ring
|
|
;
|
|
XRA A ;clear error message flag
|
|
STA ERMFLG
|
|
;
|
|
RET
|
|
|
|
; e x i t
|
|
|
|
; return to ccp
|
|
|
|
;
|
|
; Entry point for VMENU exit
|
|
;
|
|
OS$CCP:
|
|
CALL SHPOP ;clear shell stack
|
|
;
|
|
; Entry point for command line exec
|
|
;
|
|
OS$CCP1:
|
|
LXI D,TBUFF ;..tidy up..
|
|
MVI C,SETDMA ;..before going home.
|
|
CALL BDOS
|
|
|
|
IF WARMBOOT
|
|
JMP OS$BASE
|
|
ENDIF ;warmboot
|
|
|
|
IF NOT WARMBOOT
|
|
LHLD STACK ;put pointer..
|
|
SPHL ;..back to 'sp'.
|
|
RET ;return to ccp
|
|
ENDIF ;not warmboot
|
|
|
|
;
|
|
; FLOAD loads the files into the buffer, setting up the ring
|
|
; Return with NZ if load OK, Z if no files loaded
|
|
;
|
|
FILELOAD:
|
|
;
|
|
; Set up file name from System File 4
|
|
; Select all files if no entry in System File 4
|
|
;
|
|
CALL GETFN2 ;pt to first system file name
|
|
LXI D,11*3 ;pt to 4th file name
|
|
DAD D
|
|
LXI D,JOKER ;setup Joker if none
|
|
XCHG
|
|
LDAX D ;any chars?
|
|
MVI B,11 ;11 bytes
|
|
CPI ' '
|
|
CZ MOVEB
|
|
XCHG ;HL pts to system file name
|
|
LXI D,FCB+1 ;pt to FCB
|
|
MVI B,11 ;11 bytes
|
|
CALL MOVEB
|
|
;
|
|
; Build ring with filename positioned in default FCB area
|
|
;
|
|
LHLD RING ;pt to ring
|
|
MVI B,ELTSIZ ;set first element to 'noname'
|
|
FILEL1:
|
|
MVI M,1 ;store ^A's
|
|
INX H ;pt to next
|
|
BJNZ FILEL1
|
|
SHLD RINGPOS ;set ring position
|
|
SHLD RINGEND ;set ring end in case this is the only one
|
|
MVI M,0 ;store ending 0
|
|
MVI C,SETDMA ;initialize dma address..
|
|
LXI D,TBUFF ;..to default buffer.
|
|
CALL BDOS
|
|
XRA A ;clear search 'fcb'..
|
|
STA FCBEXT ;extent byte..
|
|
STA FCBRNO ;..and record number.
|
|
LXI D,FCB ;default FCB for search
|
|
CMA
|
|
MVI C,SRCHF ;..of first occurrence.
|
|
CALL BDOS
|
|
INR A ; 0ffh --> 00h if no file found
|
|
RZ
|
|
|
|
; put each found name in ring. a-reg --> offset into 'tbuf' name storage
|
|
|
|
SETRING:
|
|
DCR A ;un-do 'inr' from above and below
|
|
ADD A ;times 32 --> position index
|
|
ADD A
|
|
ADD A
|
|
ADD A
|
|
ADD A
|
|
ADI TBUFF+1 ;add page offset and..
|
|
MOV L,A ;..put address into..
|
|
MVI H,0 ;..hl-pair.
|
|
XCHG
|
|
LHLD RINGPOS ;pointer to current load point in ring
|
|
XCHG
|
|
MVI B,ELTSIZ ;move name to ring
|
|
CALL MOVE
|
|
XCHG ;de-pair contains next load point address
|
|
SHLD RINGPOS ;store and search..
|
|
MVI C,SRCHN ;..for next occurrence.
|
|
LXI D,FCB ;filename address field
|
|
CALL BDOS
|
|
INR A ;if all done, 0ffh --> 00h.
|
|
BRNZ SETRING ;if not, put next name into ring.
|
|
;
|
|
; All filenames in ring -- setup ring size and copy-buffer start point
|
|
;
|
|
LHLD RINGPOS ;next load point of ring is start of buffer
|
|
SHLD RINGEND ;set ring end..
|
|
MVI M,0 ;store ending 0
|
|
;
|
|
; Sort ring of filenames
|
|
;
|
|
SORT:
|
|
LHLD RING ;initialize 'i' sort variable and..
|
|
SHLD RINGI
|
|
LXI D,ELTSIZ ;..also 'j' variable.
|
|
DAD D
|
|
SHLD RINGJ
|
|
;
|
|
; Main Sort Loop
|
|
;
|
|
SORTLP:
|
|
LHLD RINGJ ;compare names 'i & j'
|
|
XCHG
|
|
LHLD RINGI
|
|
PUSH H ;save position pointers..
|
|
PUSH D ;..for potential swap.
|
|
|
|
; sort by file name and type
|
|
MVI B,ELTSIZ ; # of characters to compare
|
|
CALL CMPSTR ;do comparison
|
|
|
|
; final test for swapping purposes
|
|
NOCMP:
|
|
POP D
|
|
POP H
|
|
MVI B,ELTSIZ
|
|
BRNC NOSWAP
|
|
;
|
|
; Swap if 'j' string larger than 'i'
|
|
;
|
|
SWAP:
|
|
MOV C,M ;get character from one string..
|
|
LDAX D ;..and one from other string.
|
|
MOV M,A ;second into first
|
|
MOV A,C ;first into second
|
|
STAX D
|
|
INX H ;bump swap pointers
|
|
INX D
|
|
BJNZ SWAP
|
|
NOSWAP:
|
|
LHLD RINGJ ;increment 'j' pointer
|
|
LXI D,ELTSIZ
|
|
DAD D
|
|
SHLD RINGJ
|
|
XCHG ;see if end of 'j' loop
|
|
LHLD RINGEND
|
|
CALL CMPDEHL
|
|
BRNZ SORTLP ;no, so more 'j' looping.
|
|
LHLD RINGI ;bump 'i' pointer
|
|
LXI D,ELTSIZ
|
|
DAD D
|
|
SHLD RINGI
|
|
DAD D ;set start over 'j' pointer
|
|
SHLD RINGJ
|
|
XCHG ;see if end of 'i' loop
|
|
LHLD RINGEND
|
|
CALL CMPDEHL
|
|
BRNZ SORTLP ;must be more 'i' loop to do
|
|
RET
|
|
;
|
|
; left to right compare of two strings (de-pair points to 'a' string;
|
|
; hl-pair, to 'b'; b-reg contains string length.)
|
|
;
|
|
CMPSTR:
|
|
LDAX D ;get an 'a' string character and..
|
|
CMP M ;..check against 'b' string character.
|
|
RNZ ;if not equal, set flag.
|
|
INX H ;bump compare..
|
|
INX D ;..pointers and..
|
|
BJNZ CMPSTR ;..do next character.
|
|
RET
|
|
|
|
;
|
|
; Process command from table
|
|
;
|
|
CTPROC:
|
|
MOV B,A ;command in B
|
|
LXI H,CTABLE ;pt to table
|
|
MOV A,M ;any cursor commands?
|
|
ORA A
|
|
JNZ CTPR1
|
|
LXI H,CTAB1
|
|
;
|
|
; Command table scanner
|
|
; HL = Table
|
|
; B = Command Letter
|
|
;
|
|
CTPR1:
|
|
MOV A,M ;get table command char
|
|
ORA A ;end of table?
|
|
RZ ;done if so
|
|
CMP B ;match?
|
|
BRZ CTPR2
|
|
INX H ;skip to next entry
|
|
INX H
|
|
INX H
|
|
BR CTPR1
|
|
CTPR2:
|
|
INX H ;pt to address
|
|
MOV A,M ;get low
|
|
INX H
|
|
MOV H,M ;get high
|
|
MOV L,A
|
|
XTHL ;address on stack
|
|
RET ;"jump" to routine
|
|
|
|
; Command Table
|
|
CTABLE:
|
|
DB 0 ;user cursor positioning
|
|
DW UP
|
|
DB 0
|
|
DW DOWN
|
|
DB 0
|
|
DW FORWARD
|
|
DB 0
|
|
DW REVERSE
|
|
CTAB1:
|
|
DB CTRLC ;if exit, then to opsys
|
|
DW OS$CCP
|
|
DB CTRLR ;screen refresh?
|
|
DW RUNSH3
|
|
DB CTRLE ;system cursor positioning
|
|
DW UP
|
|
DB CTRLX
|
|
DW DOWN
|
|
DB CTRLD
|
|
DW FORWARD
|
|
DB CTRLS
|
|
DW REVERSE
|
|
DB CR ;nop
|
|
DW LOOP
|
|
DB '+' ;jump forward
|
|
DW JUMPF
|
|
DB '-' ;jump backward
|
|
DW JUMPB
|
|
DB ' ' ;go forward
|
|
DW FORWARD
|
|
DB BS ;back up?
|
|
DW REVERSE
|
|
;
|
|
DB 0 ;end of table
|
|
|
|
;
|
|
; COMMAND: - (Previous Screen)
|
|
;
|
|
JUMPB:
|
|
LXI H,CURHOME ;set cursor home
|
|
SHLD CURAT
|
|
LHLD RING ;at front?
|
|
XCHG
|
|
LHLD LOCBEG
|
|
CALL CMPDEHL
|
|
BRZ JUMPBW ;back up and wrap around
|
|
SHLD LOCEND ;set new end
|
|
LXI D,-EPS*ELTSIZ ;back up
|
|
DAD D
|
|
SHLD LOCBEG ;new beginning
|
|
SHLD RINGPOS ;new position
|
|
JMP RUNSH3
|
|
JUMPBW:
|
|
LHLD LOCBEG ;at first screen?
|
|
XCHG
|
|
LHLD RING ;pt to first element of ring
|
|
CALL CMPDEHL
|
|
BRZ JBW0 ;advance to end
|
|
LXI H,-EPS*ELTSIZ ;back up
|
|
DAD D ;first element of new local ring
|
|
BR JFW0
|
|
JBW0:
|
|
LXI D,EPS*ELTSIZ ;pt to next screen
|
|
DAD D
|
|
XCHG
|
|
LHLD RINGEND
|
|
CALL CMPDEHL
|
|
XCHG
|
|
BRZ JBW1
|
|
BRC JBW0
|
|
JBW1:
|
|
LXI D,-EPS*ELTSIZ
|
|
DAD D ;pt to first element of new local ring
|
|
BR JFW0
|
|
;
|
|
; COMMAND: + (Next Screen)
|
|
;
|
|
JUMPF:
|
|
LXI H,CURHOME ;set cursor to home
|
|
SHLD CURAT
|
|
LHLD LOCEND ;see if Local End <= Ring End
|
|
XCHG
|
|
LHLD RINGEND
|
|
CALL CMPDEHL
|
|
BRZ CMDLOOP
|
|
LHLD LOCEND ;new screen starting at LOCEND
|
|
BR JFW0
|
|
|
|
;
|
|
; Reset to Beginning of RING and Resume Command Looping
|
|
;
|
|
CMDLOOP:
|
|
CALL SETSCR ;reset all screen pointers
|
|
CMDLRET:
|
|
JMP RUNSH3
|
|
;
|
|
; Reset RING Position to HL
|
|
;
|
|
JFW0:
|
|
CALL SETSCR1 ;reset RINGPOS on ...
|
|
BR CMDLRET
|
|
;
|
|
; Reset Local Ring to HL
|
|
;
|
|
JFW0A:
|
|
CALL SETSCR2 ;reset LOCBEG on ...
|
|
BR CMDLRET
|
|
|
|
;
|
|
; COMMAND: ' ', Left-Arrow
|
|
;
|
|
FORWARD:
|
|
CALL CLRCUR ;clear cursor
|
|
CALL FOR0 ;position on screen and in ring
|
|
CALL SETCUR ;set cursor
|
|
JMP LOOPFN
|
|
; advance routine
|
|
FOR0:
|
|
LHLD RINGPOS ;at end of loop yet?
|
|
LXI D,ELTSIZ ;i.e., will we be at end of loop?
|
|
DAD D
|
|
XCHG
|
|
LHLD LOCEND
|
|
CALL CMPDEHL ;compare 'present' to 'end'
|
|
BRNZ FORW ;to next print position
|
|
CALL CUR$FIRST ;position cursor
|
|
LHLD LOCBEG ;set position pointer to beginning and..
|
|
SHLD RINGPOS
|
|
RET
|
|
FORW:
|
|
LHLD RINGPOS ;advance in ring
|
|
LXI D,ELTSIZ
|
|
DAD D
|
|
SHLD RINGPOS ;new position
|
|
CALL CUR$NEXT ;position cursor
|
|
RET
|
|
|
|
;
|
|
; COMMAND: BS, Right-Arrow
|
|
;
|
|
REVERSE:
|
|
CALL CLRCUR ;clear cursor
|
|
CALL REV0 ;position on screen and in ring
|
|
CALL SETCUR ;set cursor
|
|
JMP LOOPFN
|
|
; Back Up Routine
|
|
REV0:
|
|
LHLD LOCBEG
|
|
XCHG
|
|
LHLD RINGPOS ;see if at beginning of ring
|
|
CALL CMPDEHL
|
|
BRNZ REV1 ;skip position pointer reset if not..
|
|
CALL CUR$LAST ;end of local ring
|
|
LHLD LOCEND ;set to end +1 to backup to end
|
|
LXI D,-ELTSIZ
|
|
DAD D
|
|
SHLD RINGPOS
|
|
RET
|
|
REV1:
|
|
CALL CUR$BACK ;back up 1
|
|
REV2:
|
|
LHLD RINGPOS
|
|
LXI D,-ELTSIZ ;one ring position..
|
|
DAD D ;..backwards.
|
|
SHLD RINGPOS
|
|
RET
|
|
|
|
;
|
|
; COMMAND: Up-Arrow
|
|
;
|
|
UP:
|
|
CALL CLRCUR ;clear cursor
|
|
LHLD RINGPOS ;see if wrap around
|
|
LXI D,-ELTSIZ*4 ;4 entries
|
|
DAD D
|
|
XCHG
|
|
LHLD LOCBEG ;beginning of local screen
|
|
CALL CMPDEHL
|
|
BRC UP2 ;wrap around
|
|
MVI B,4 ;back up 4 entries
|
|
UP1:
|
|
PUSH B ;save count
|
|
CALL REV0 ;back up in ring and on screen (no print)
|
|
POP B ;get count
|
|
BJNZ UP1
|
|
BR DOWN1A
|
|
UP2:
|
|
LHLD RINGPOS ;advance to beyond end
|
|
LXI D,ELTSIZ*4
|
|
DAD D
|
|
XCHG
|
|
LHLD LOCEND ;compare to local end
|
|
XCHG
|
|
CALL CMPDEHL
|
|
BRZ DOWN1A ;at end, so too far
|
|
BRC DOWN1A ;beyond end, so back up
|
|
SHLD RINGPOS ;new ring position
|
|
LHLD CURAT ;advance cursor
|
|
INR H ;next line
|
|
SHLD CURAT
|
|
BR UP2
|
|
|
|
;
|
|
; COMMAND: Down-Arrow
|
|
;
|
|
DOWN:
|
|
CALL CLRCUR ;clear cursor
|
|
LHLD RINGPOS ;see if wrap around
|
|
LXI D,ELTSIZ*4 ;4 entries
|
|
DAD D
|
|
XCHG
|
|
LHLD LOCEND ;end of local screen
|
|
XCHG
|
|
CALL CMPDEHL
|
|
BRZ DOWN2 ;wrap around
|
|
BRC DOWN2 ;wrap around
|
|
MVI B,4 ;forward 4 entries
|
|
DOWN1:
|
|
PUSH B ;save count
|
|
CALL FOR0 ;advance in ring and on screen (no print)
|
|
POP B ;get count
|
|
BJNZ DOWN1
|
|
DOWN1A:
|
|
CALL SETCUR ;set cursor
|
|
JMP LOOPFN
|
|
DOWN2:
|
|
LHLD CURAT ;preserve column
|
|
MOV B,L ;column number in B
|
|
LXI H,CURHOME ;home position
|
|
SHLD CURAT ;set new position
|
|
LHLD LOCBEG ;beginning of local ring
|
|
SHLD RINGPOS ;new ring position
|
|
DOWN3:
|
|
LHLD CURAT ;check for at top of column
|
|
MOV A,L ;get col
|
|
CMP B ;there?
|
|
BRZ DOWN1A
|
|
LHLD RINGPOS ;advance in ring
|
|
LXI D,ELTSIZ ;ELTSIZ bytes/entry
|
|
DAD D
|
|
SHLD RINGPOS
|
|
LHLD CURAT ;get cursor position
|
|
LXI D,19 ;advance 19 bytes/screen entry
|
|
DAD D
|
|
SHLD CURAT
|
|
BR DOWN3
|
|
|
|
;
|
|
;**************************************************
|
|
;
|
|
; WORKHORSE Routines
|
|
;
|
|
; conin routine (waits for response)
|
|
;
|
|
KEYIN:
|
|
CALL CIN ;get input
|
|
JMP CAPS ;capitalize
|
|
|
|
;
|
|
; Fill buffer with 'spaces' with count in b-reg
|
|
;
|
|
FILL:
|
|
MVI M,' ' ;put in space character
|
|
INX H
|
|
BJNZ FILL ;no, branch.
|
|
RET
|
|
;
|
|
; Check for legal filename character -- return with carry set if illegal
|
|
;
|
|
CKLEGAL:
|
|
LDAX D ;get character from de-pair
|
|
INX D ;point at next character
|
|
CPI ' ' ;less than space?
|
|
RC ;return carry if unpermitted character
|
|
PUSH H
|
|
PUSH B
|
|
CPI '[' ;if greater than 'z', exit with..
|
|
BRNC CKERR ;..carry set.
|
|
MVI B,CHR$TEND-CHR$TBL
|
|
LXI H,CHR$TBL
|
|
CHR$LP:
|
|
CMP M
|
|
BRZ CKERR
|
|
INX H
|
|
BJNZ CHR$LP
|
|
ORA A ;clear carry for good character
|
|
POP B
|
|
POP H
|
|
RET
|
|
|
|
CKERR:
|
|
POP B
|
|
POP H
|
|
STC ;error exit with carry set
|
|
RET
|
|
|
|
CHR$TBL:
|
|
DB ',',':',';','<','=','>' ;invalid character table
|
|
CHR$TEND:
|
|
DS 0
|
|
;
|
|
; Print file name pted to by HL
|
|
; Advance HL 11 bytes
|
|
;
|
|
PRFN:
|
|
MOV A,M ;check for 'noname'
|
|
CPI 1 ;no name?
|
|
BRZ PRFN1
|
|
MVI B,8 ;8 chars
|
|
CALL PRFNS1
|
|
MVI A,'.'
|
|
CALL COUT
|
|
MVI B,3 ;file type and fall thru
|
|
PRFNS1:
|
|
MOV A,M ;get char
|
|
CALL COUT
|
|
INX H ;pt to next
|
|
BJNZ PRFNS1
|
|
RET
|
|
PRFN1:
|
|
CALL VPRINT
|
|
DB ' No File'
|
|
DB ' '
|
|
DB ' ',0
|
|
MVI B,11 ;advance 11 chars
|
|
PRFN2:
|
|
INX H ;pt to next
|
|
BJNZ PRFN2
|
|
RET
|
|
|
|
;
|
|
; move subroutine -- move b-reg # of bytes from hl-pair to de-pair
|
|
;
|
|
MOVE:
|
|
MOV A,M ;get hl-pair referenced source byte
|
|
ANI 7FH ;strip attributes
|
|
STAX D ;put to de-pair referenced destination
|
|
INX H ;fix pointers for next search
|
|
INX D
|
|
BJNZ MOVE
|
|
RET
|
|
|
|
MOVEB:
|
|
PUSH H ;SAVE HL, DE
|
|
PUSH D
|
|
CALL MOVE
|
|
POP D ;RESTORE DE, HL
|
|
POP H
|
|
RET
|
|
;
|
|
; Compare de-pair to hl-pair and set flags accordingly
|
|
;
|
|
CMPDEHL:
|
|
MOV A,D ;see if high bytes set flags
|
|
CMP H
|
|
RNZ ;return if not equal
|
|
MOV A,E
|
|
CMP L ;low bytes set flags instead
|
|
RET
|
|
;
|
|
; Shift hl-pair b-reg bits (-1) to right (divider routine)
|
|
;
|
|
SHIFTLP:
|
|
DCR B
|
|
RZ
|
|
MOV A,H
|
|
ORA A
|
|
RAR
|
|
MOV H,A
|
|
MOV A,L
|
|
RAR
|
|
MOV L,A
|
|
BR SHIFTLP
|
|
|
|
;
|
|
;**************************************************
|
|
;
|
|
; MESSAGE Routines
|
|
;
|
|
; Print VMENU Banner
|
|
;
|
|
BANNER:
|
|
CALL VCLS ;clear screen
|
|
LXI H,BANADR
|
|
CALL GOTOXY
|
|
CALL VPRINT ;print banner
|
|
DB 'VMENU, Version '
|
|
DB VERS/10+'0','.',(VERS MOD 10)+'0'
|
|
IF Z80
|
|
DB ' ',DIM,'[Z80 Code]',BRIGHT
|
|
ELSE
|
|
DB ' ',DIM,'[8080 Code]',BRIGHT
|
|
ENDIF
|
|
DB 0
|
|
RET
|
|
;
|
|
; Print DU:DIR and MORE Message
|
|
;
|
|
DIRMORE:
|
|
LXI H,DUADR ; POSITION CURSOR
|
|
CALL GOTOXY
|
|
CALL RETUD ; GET CURRENT DISK AND USER
|
|
MOV A,B ; PRINT DISK
|
|
ADI 'A'
|
|
CALL COUT
|
|
MOV A,C ; PRINT USER
|
|
CALL PAFDC ; FLOADING DECIMAL
|
|
MVI A,':'
|
|
CALL COUT
|
|
CALL DUTDIR ; GET DIR NAME
|
|
BRZ NODIR
|
|
MVI B,8 ; 8 CHARS IN NAME
|
|
PRNAME:
|
|
MOV A,M ; GET CHAR
|
|
CPI ' '+1 ; CHECK FOR DONE
|
|
BRC PRMORE
|
|
CALL COUT ; PRINT CHAR
|
|
INX H
|
|
BJNZ PRNAME
|
|
BR PRMORE
|
|
NODIR:
|
|
CALL VPRINT
|
|
DB 'Noname',0
|
|
PRMORE:
|
|
LDA MORE ; CHECK FLAG
|
|
ORA A ; 0=NO MORE
|
|
RZ
|
|
LXI H,MOREADR
|
|
CALL GOTOXY ; POSITION CURSOR
|
|
CALL VPRINT
|
|
DB DIM,'[More Files]',BRIGHT,0
|
|
RET
|
|
|
|
;
|
|
; Home the Cursor
|
|
;
|
|
CUR$FIRST:
|
|
LXI H,CURHOME ; HOME ADDRESS
|
|
SHLD CURAT ; SET CURSOR POSITION
|
|
JMP GOTOXY
|
|
;
|
|
; Last File Position
|
|
;
|
|
CUR$LAST:
|
|
LHLD RINGPOS ; ADVANCE
|
|
SHLD LOCPOS ; SET LOCAL POSITION
|
|
CL0:
|
|
LXI D,ELTSIZ
|
|
DAD D
|
|
XCHG
|
|
LHLD LOCEND ; END OF LOCAL RING?
|
|
CALL CMPDEHL
|
|
RZ
|
|
XCHG ; NEW POSITION
|
|
SHLD LOCPOS
|
|
PUSH H ; SAVE POSITION
|
|
CALL CUR$NEXT ; ADVANCE CURSOR
|
|
POP H ; GET POSITION
|
|
BR CL0
|
|
;
|
|
; Advance the Cursor
|
|
;
|
|
CUR$NEXT:
|
|
LHLD CURAT ; COMPUTE NEW POSITION
|
|
MOV A,L ; CHECK FOR NEW LINE
|
|
ADI 19 ; SIZE OF EACH ENTRY
|
|
CPI 70
|
|
BRNC CN1 ; ADVANCE TO NEXT LINE
|
|
MOV L,A ; NEW POSITION
|
|
SHLD CURAT
|
|
JMP GOTOXY
|
|
CN1:
|
|
MOV A,H ; GET LINE
|
|
LXI H,CURHOME ; GET COL
|
|
MOV H,A ; SET LINE AND FALL GO TO CUR$DOWN
|
|
SHLD CURAT
|
|
BR CUR$DOWN
|
|
;
|
|
; Back Up the Cursor
|
|
;
|
|
CUR$BACK:
|
|
LXI H,CURHOME ; GET HOME
|
|
XCHG ; ... IN DE
|
|
LHLD CURAT
|
|
CALL CMPDEHL ; COMPARE
|
|
BRZ CUR$LAST ; GOTO END IF LAST
|
|
MOV A,L ; CHECK FOR FIRST COL
|
|
CMP E
|
|
BRZ CB1
|
|
SUI 19 ; BACK UP ONE COL
|
|
MOV L,A
|
|
SHLD CURAT ; NEW POS
|
|
JMP GOTOXY
|
|
CB1:
|
|
MOV A,E ; GET HOME COL
|
|
ADI 19*3 ; GET LAST COL
|
|
MOV L,A
|
|
DCR H ; PREV LINE
|
|
SHLD CURAT
|
|
JMP GOTOXY
|
|
;
|
|
; Move Cursor Down One Line
|
|
;
|
|
CUR$DOWN:
|
|
LXI H,CURHOME ; GET HOME ADDRESS
|
|
MOV B,H ; LINE IN B
|
|
LHLD CURAT ; GET CURRENT ADDRESS
|
|
INR H ; MOVE DOWN
|
|
MOV A,H ; CHECK FOR TOO FAR
|
|
SUB B
|
|
CPI EPS/4
|
|
BRNC CD1
|
|
SHLD CURAT ; OK, SO SET POSITION
|
|
JMP GOTOXY
|
|
CD1:
|
|
MOV A,L ; GET COL
|
|
LXI H,CURHOME
|
|
MOV L,A
|
|
SHLD CURAT
|
|
JMP GOTOXY
|
|
;
|
|
; Refresh Screen
|
|
;
|
|
REFRESH:
|
|
LHLD CURAT ; SAVE CURSOR AND RING POSITIONS
|
|
SHLD SCURAT
|
|
LHLD RINGPOS
|
|
SHLD SRINGPOS
|
|
CALL BANNER ; PRINT BANNER
|
|
CALL DIRMORE ; PRINT CURRENT DIRECTORY AND MORE MESSAGE
|
|
CALL DISPFILES ; DISPLAY FILES
|
|
CALL DISPMENU ; DISPLAY MENU
|
|
LHLD SCURAT ; RESTORE CURSOR AND RING POSITIONS
|
|
SHLD CURAT
|
|
LHLD SRINGPOS
|
|
SHLD RINGPOS
|
|
CALL SETCUR ; RESTORE CURSOR ON SCREEN
|
|
call atcmd
|
|
call vprint
|
|
db DIM,'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 vprint
|
|
db ') - ',BRIGHT,0
|
|
RET
|
|
|
|
;
|
|
; Print ZCPR3 Return Prompt
|
|
;
|
|
prmptc:
|
|
call vprint
|
|
db ', ^C=Z3',0
|
|
ret
|
|
;
|
|
; Print First/Last Menu Chars
|
|
;
|
|
prmptf:
|
|
call vprint
|
|
db ', ',RFM,'=1st Menu, ',RLM,'=Prev Menu',0
|
|
ret
|
|
;
|
|
; Print next menu message
|
|
;
|
|
prmptn:
|
|
call vprint
|
|
db ', ',RNM,'=Next Menu',0
|
|
ret
|
|
|
|
;
|
|
; Refresh File Display
|
|
;
|
|
DISPFILES:
|
|
CALL CUR$FIRST ; POSITION CURSOR AT FIRST POSITION
|
|
LHLD LOCBEG ; PT TO FIRST FILE NAME
|
|
SHLD LOCPOS ; SAVE LOCAL POSITION
|
|
DSPF1:
|
|
LHLD LOCEND ; AT END?
|
|
XCHG
|
|
LHLD LOCPOS
|
|
CALL CMPDEHL
|
|
JZ CUR$FIRST ; POSITION AT FIRST ENTRY AND RETURN
|
|
MVI B,4 ; 4 SPACES
|
|
MVI A,' '
|
|
DSPF2:
|
|
CALL COUT
|
|
BJNZ DSPF2
|
|
CALL PRFN ; PRINT FILE NAME (HL IS ADVANCED)
|
|
SHLD LOCPOS
|
|
CALL CUR$NEXT ; ADVANCE CURSOR
|
|
BR DSPF1
|
|
;
|
|
; Position Cursor at CURAT
|
|
;
|
|
SETCUR:
|
|
LHLD CURAT
|
|
CALL GOTOXY
|
|
CALL VPRINT
|
|
DB '-->',0
|
|
RET
|
|
;
|
|
; Clear Cursor
|
|
;
|
|
CLRCUR:
|
|
LHLD CURAT
|
|
CALL GOTOXY
|
|
CALL VPRINT
|
|
DB ' ',0
|
|
RET
|
|
;
|
|
; Working Message
|
|
;
|
|
WORKMSG:
|
|
CALL ERMSG
|
|
DB DIM,'Working ...',BRIGHT,0
|
|
RET
|
|
;
|
|
; Error Message
|
|
;
|
|
ERMSG:
|
|
MVI A,0FFH ; SET ERROR MESSAGE FLAG
|
|
STA ERMFLG
|
|
LXI H,ERADR ; GET ADDRESS
|
|
CALL GOTOXY
|
|
JMP VPRINT
|
|
;
|
|
; Clear Error Message
|
|
;
|
|
ERCLR:
|
|
XRA A ; CLEAR FLAG
|
|
STA ERMFLG
|
|
LXI H,ERADR ; POSITION
|
|
CALL GOTOXY
|
|
PUSH B
|
|
MVI B,76-(ERADR MOD 255)
|
|
CALL VEREOL ; ERASE TO EOL
|
|
POP B
|
|
RET
|
|
;
|
|
; Position at Command Prompt and Clear It
|
|
;
|
|
ATCMD:
|
|
LXI H,CPMADR ; POSITION
|
|
CALL GOTOXY
|
|
PUSH B
|
|
MVI B,76-(CPMADR MOD 255)
|
|
CALL VEREOL ; CLEAR MESSAGE
|
|
POP B
|
|
LXI H,CPMADR ; REPOSITION
|
|
JMP GOTOXY
|
|
;
|
|
; Position at Bottom of Screen and Prompt for Continuation
|
|
;
|
|
BOTTOM:
|
|
LXI H,BOTADR ; POSITION
|
|
CALL GOTOXY
|
|
;
|
|
; Prompt for Continuation
|
|
;
|
|
SAK:
|
|
CALL VPRINT
|
|
DB DIM,'Strike Any Key -- ',BRIGHT,0
|
|
JMP KEYIN
|
|
|
|
;
|
|
; Open Menu File
|
|
;
|
|
menuload:
|
|
lhld menufcb ;pt to menu fcb
|
|
inx h
|
|
push h
|
|
call getfn2 ;copy FCB into MENU FCB
|
|
lxi d,11*2 ;pt to 3rd system file name
|
|
dad d
|
|
pop d ;DE pts to first char of MENU FCB file name
|
|
mvi b,11 ;11 bytes
|
|
call moveb
|
|
dcx d ;pt to fcb
|
|
call initfcb ;init fcb
|
|
call f$open ;open file
|
|
brz menu1 ;abort if no menu
|
|
call vprint
|
|
db CR,LF,' File ',0
|
|
lhld menufcb ;pt to file name
|
|
inx h
|
|
call prfn
|
|
call vprint
|
|
db ' Not Found',0
|
|
jmp os$ccp ;abort
|
|
;
|
|
; Load Menu File from disk
|
|
;
|
|
menu1:
|
|
call menustrt ;get address of buffer for menu load
|
|
xchg ;... in DE
|
|
;
|
|
; Load next block from Menu File -- DE pts to Load Address
|
|
;
|
|
mload:
|
|
lhld menufcb ;pt to FCB
|
|
xchg ;... in DE, HL = load address
|
|
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 move
|
|
lhld bdos+1 ;get address of top of TPA
|
|
mov a,h ;set to bottom of ZCPR3
|
|
sui 10
|
|
cmp d ;about to overflow ZCPR3?
|
|
brnc mload ;continue if not
|
|
call vprint
|
|
db CR,LF,' TPA Full',0
|
|
jmp os$ccp
|
|
|
|
;
|
|
; Init Flags and Clear MSB of all bytes in Menu File
|
|
;
|
|
mloaddn:
|
|
call f$close ;close input file
|
|
mvi m,CTRLZ ;ensure EOF mark
|
|
xra a ;A=0
|
|
sta cpmok ;turn off ZCPR3 return flag
|
|
call menustrt ;pt to first menu char
|
|
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
|
|
;
|
|
; 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 lskipt ;skip to beginning of next menu
|
|
brz menul2 ;resume if at beginning of next menu
|
|
cpi CTRLZ ;error?
|
|
jz mstrerr
|
|
br menul4
|
|
;
|
|
; Check Menu Options
|
|
;
|
|
menul5:
|
|
call menustrt ;pt to first menu char
|
|
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 XOPTION ;exit OK?
|
|
jnz mstrerr ;option error if not
|
|
;
|
|
; Disable Exit to ZCPR3
|
|
;
|
|
mvi a,0FFH ;turn flag off
|
|
sta cpmok
|
|
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
|
|
ret
|
|
|
|
;
|
|
; Entry Point for Menu Display
|
|
;
|
|
dispmenu:
|
|
mvi h,epsline ;pt to first line of menu
|
|
mvi l,1 ;col 1
|
|
call gotoxy ;position there
|
|
lhld mstart ;pt to first byte of current menu
|
|
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
|
|
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
|
|
cpi XOPTION ;ZCPR3 return?
|
|
jnz mstrerr ;error if not
|
|
;
|
|
; Toggle ZCPR3 Return Option
|
|
;
|
|
lda cpmok ;get flag
|
|
cma ;toggle
|
|
sta cpmok
|
|
br dispm1
|
|
;
|
|
; Done with Menu-Specific Option Processing
|
|
;
|
|
dispm2:
|
|
call lskip ;skip to LF
|
|
call getnlines ;get line count in A
|
|
sta pagcnt ;set count
|
|
;
|
|
; 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
|
|
;
|
|
dispm4:
|
|
call lskip ;skip to first char of next line (option char)
|
|
shld optstrt ;set start address of options
|
|
;
|
|
; Determine if Another Menu Follows
|
|
;
|
|
xra a ;A=0
|
|
sta nmenfl ;set for no next menu
|
|
dispm5:
|
|
mov a,m ;ok?
|
|
ani 7FH ;mask
|
|
cpi CTRLZ ;error if EOF
|
|
jz mstrerr
|
|
cpi MINDIC ;next menu?
|
|
brnz dispm6
|
|
inx h ;double indicator if end
|
|
mov a,m
|
|
cpi MINDIC ;end?
|
|
rz
|
|
mvi a,0FFH ;set next menu
|
|
sta nmenfl
|
|
ret
|
|
dispm6:
|
|
call lskip ;skip to next line
|
|
br dispm5
|
|
|
|
;
|
|
; Ready for Option Input
|
|
; The following Flags/Values are now set:
|
|
; OPTSTRT -- Address of First Menu Option
|
|
; NMENFL -- 0 if no next menu, 0FFH if next menu
|
|
; CSTART -- Address of First Char of Current Menu
|
|
; MSTART -- Start Address of MINDIC Before Menu Display
|
|
; (MSTART)=MFIRST with MSB Set
|
|
prompt:
|
|
lxi h,cpadr ;position for input
|
|
call gotoxy
|
|
mvi a,0ffh
|
|
sta pagcnt ;turn off paging
|
|
call keyin ;get user input
|
|
PUSH PSW ;save command
|
|
LDA ERMFLG ;error message?
|
|
ORA A ;0=no
|
|
CNZ ERCLR ;erase old error message
|
|
POP PSW ;get command
|
|
ret
|
|
|
|
;
|
|
; Process Command
|
|
;
|
|
cmdproc:
|
|
call ctproc ;process movement or exit command
|
|
|
|
;
|
|
; Check for Command to Return to First Menu
|
|
;
|
|
lhld cstart ;pt to first char of menu
|
|
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
|
|
call putshm ;reenter menu system at new menu
|
|
jmp os$ccp1
|
|
;
|
|
; 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
|
|
call putshm ;reenter shell at last menu
|
|
jmp os$ccp1
|
|
;
|
|
; This is where additional functions may be added
|
|
;
|
|
prmpt3:
|
|
|
|
;
|
|
; Check for Option Letter
|
|
;
|
|
lhld optstrt ;pt to first option char
|
|
prmptx:
|
|
mov a,m ;get it
|
|
ani 7FH ;mask MSB
|
|
call caps ;capitalize
|
|
cpi MINDIC ;at next menu?
|
|
rz
|
|
cmp b ;match user selection?
|
|
brz prmptd
|
|
call lskip ;skip to next line
|
|
br prmptx
|
|
|
|
;
|
|
; Process Option
|
|
;
|
|
prmptd:
|
|
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 os$ccp1 ;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 ibuf ;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
|
|
|
|
;
|
|
; 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 ;increment for following decrement
|
|
lhld mstart ;pt to start of 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
|
|
cpi CTRLZ ;EOF?
|
|
jz mstrerr
|
|
mchc3:
|
|
call lskipt ;skip to next line
|
|
brnz mchc3 ;continue if not at end of menu commands
|
|
cpi CTRLZ ;EOF?
|
|
jz mstrerr
|
|
inx h ;end of MENU.MNU?
|
|
mov a,m ;yes if double MINDIC
|
|
ani 7FH ;mask
|
|
cpi MINDIC
|
|
jz mstrerr ;error if so
|
|
dcx h ;pt to first char
|
|
br mchc1 ;continue
|
|
|
|
;
|
|
; 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:
|
|
lda pagcnt ;check for page overflow
|
|
ora a ;do nothing
|
|
brz lskip ;... except skip out line
|
|
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 BRIGHT ;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
|
|
ret
|
|
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
|
|
|
|
;
|
|
; 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
|
|
cpi CTRLZ ;EOF?
|
|
rz
|
|
inx h ;pt to next
|
|
cpi LF ;EOL?
|
|
brnz lskip
|
|
ret
|
|
|
|
;
|
|
; Menu Structure Error -- FATAL
|
|
; This message is printed to indicate an error in the structure of
|
|
; the MENU.MNU file.
|
|
;
|
|
mstrerr:
|
|
call vprint
|
|
db CR,LF,' Structure Error',0
|
|
jmp os$ccp
|
|
|
|
;
|
|
; Expand Line Pted to by HL into Scratch Area
|
|
; Return with HL pting to next line, DE pting to current line
|
|
;
|
|
expand:
|
|
xchg
|
|
lxi h,noname ;init no name file
|
|
mvi m,1 ;set no entry
|
|
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
|
|
ani 7FH ;mask
|
|
call caps ;capitalize variable
|
|
cpi FPDISK ;current disk?
|
|
brz expdisk
|
|
cpi FPUSER ;current user?
|
|
brz expuser
|
|
cpi FPFILE ;filename.typ?
|
|
brz expfile
|
|
cpi FPNAME ;filename?
|
|
brz expname
|
|
cpi FPPTR ;file being pointed to?
|
|
brz exppfile
|
|
cpi FPTYPE ;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
|
|
;
|
|
; Expand File at Pointer
|
|
;
|
|
exppfile:
|
|
mov a,m ;get option char
|
|
ani 7FH ;mask
|
|
call caps ;capitalize
|
|
cpi FPFILE ;filename.typ?
|
|
brz exppf
|
|
cpi FPNAME ;filename only?
|
|
brz exppn
|
|
cpi FPTYPE ;filetype only?
|
|
brz exppt
|
|
jmp exp1 ;abort if error
|
|
;
|
|
; Extract full filename.typ of file being pointed to
|
|
;
|
|
exppf:
|
|
inx h ;pt to next char
|
|
push h ;save ptr to next char
|
|
lhld ringpos ;set ring position
|
|
call cknoname ;check and substitute no file
|
|
call putn ;put name pted to by HL
|
|
mvi a,'.' ;store dot
|
|
stax d
|
|
inx d
|
|
call putt ;put type pted to by HL
|
|
pop h
|
|
jmp exp1 ;continue
|
|
;
|
|
; Expand file name of file being pointed to
|
|
;
|
|
exppn:
|
|
inx h ;pt to next char
|
|
push h ;save ptr to next char
|
|
lhld ringpos ;set ring position
|
|
call cknoname ;check and substitute no file
|
|
call putn ;put name
|
|
pop h
|
|
jmp exp1
|
|
;
|
|
; Expand file type of file being pointed to
|
|
;
|
|
exppt:
|
|
inx h ;pt to next char
|
|
push h ;save ptr to next char
|
|
push d ;save DE
|
|
lhld ringpos ;pt to ring entry
|
|
call cknoname ;check and substitute no file
|
|
lxi d,8 ;pt to file type
|
|
dad d
|
|
pop d ;get DE
|
|
call putt ;put type
|
|
pop h
|
|
jmp exp1
|
|
;
|
|
; Check to see if HL pts to 'noname' and, if so, substitute name
|
|
;
|
|
cknoname:
|
|
push d ;save DE
|
|
push b ;save BC
|
|
call ckno ;do check
|
|
pop b ;get BC
|
|
pop d ;restore DE
|
|
ret
|
|
ckno:
|
|
mov a,m ;get char
|
|
cpi 1 ;no name?
|
|
rnz
|
|
lxi h,noname ;pt to no name
|
|
mov a,m ;check for definition
|
|
cpi 1 ;no name?
|
|
rnz
|
|
xchg ;HL pts to file name
|
|
call ermsg
|
|
db 'File Name? ',0
|
|
lhld ibuf ;pt to input buffer
|
|
mvi a,0ffh ;capitalize input
|
|
call bline ;get line from user
|
|
call sksp ;skip spaces
|
|
xchg
|
|
lhld menufcb ;pt to dummy FCB
|
|
xchg
|
|
call zprsfn ;parse file name into FCB
|
|
inx d ;pt to first char
|
|
lxi h,noname ;pt to name buffer
|
|
xchg
|
|
mvi b,11 ;copy into buffer
|
|
call moveb
|
|
ret ;HL pts to name
|
|
;
|
|
; 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
|
|
sui EPSLINE+1 ;subtract number of lines in file display
|
|
; ... + 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
|
|
|
|
;
|
|
; Compute Address of Buffer for Menu Load
|
|
;
|
|
menustrt:
|
|
lhld ringend ;get address of buffer for menu load
|
|
inr h ;next page
|
|
mvi l,0
|
|
ret
|
|
|
|
;
|
|
; S T O R A G E
|
|
;
|
|
; Initialized
|
|
;
|
|
FILERCMD:
|
|
VMNAME ;VMENU Name
|
|
VMNFILL ;Filler
|
|
DB ' ' ;one space
|
|
DB 0 ;end of shell command
|
|
JOKER:
|
|
DB '???????????' ;*.* equivalent
|
|
MENUFILE:
|
|
db 'MENU '
|
|
db 'VMN'
|
|
|
|
;
|
|
; Uninitialized
|
|
;
|
|
STACK:
|
|
DS 2
|
|
BUFFER:
|
|
DS 2 ;buffer start
|
|
CURAT:
|
|
DS 2 ;current cursor position
|
|
ERMFLG:
|
|
DS 1 ;error message flag
|
|
EXPLINE:
|
|
DS 2 ;buffer to expand line in
|
|
H$DR:
|
|
DS 1 ;home drive
|
|
H$U$A:
|
|
DS 1 ;home user area (must follow H$DR)
|
|
IBUF:
|
|
DS 2 ;input line buffer
|
|
LOCBEG:
|
|
DS 2 ;local beginning of ring
|
|
LOCEND:
|
|
DS 2 ;local end of ring
|
|
LOCPOS:
|
|
DS 2 ;local ring position (temp)
|
|
MENUFCB:
|
|
DS 2 ;FCB for Menu File
|
|
NONAME:
|
|
DS 11 ;dummy user-defined file name
|
|
RING:
|
|
DS 2 ;ptr to beginning of ring
|
|
RINGI:
|
|
DS 2 ;ring sort pointer
|
|
RINGJ:
|
|
DS 2 ;another ring sort pointer
|
|
RINGEND:
|
|
DS 2 ;current ring end pointer
|
|
RINGPOS:
|
|
DS 2 ;current ring position in scan
|
|
SCURAT:
|
|
DS 2 ;save cursor position
|
|
SRINGPOS:
|
|
DS 2 ;save ring position
|
|
;
|
|
; Menu Buffers
|
|
;
|
|
more:
|
|
ds 1 ;More Files Flag
|
|
optstrt:
|
|
ds 2 ;Address of First Option in Current Menu
|
|
mstart:
|
|
ds 2 ;Address of First Menu
|
|
cstart:
|
|
ds 2 ;Address of Current Menu
|
|
nmenfl:
|
|
ds 1 ;Next Menu Available Flag (0=No)
|
|
menuno:
|
|
ds 1 ;Number of Menu
|
|
pagcnt:
|
|
ds 1 ;Paging Counter
|
|
cpmok:
|
|
ds 1 ;OK to Return to ZCPR3 (0=No)
|
|
|
|
END
|
|
|
|
|