mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
2655 lines
52 KiB
Plaintext
2655 lines
52 KiB
Plaintext
; 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
|
||
|
||
|