;  PROGRAM:  RENAME
;  VERSION:  2.0
;  DATE:  16 JAN 83
;  AUTHOR:  RICHARD CONN
;  PREVIOUS VERSIONS:  1.4 (6 JAN 83), 1.3 (7 DEC 82), 1.2 (10 NOV 82)
;  PREVIOUS VERSION:  RENAME.ASM Version 1.1 (26 OCT 81)
VERS    equ     20

;
;       This program is Copyright (c) 1982, 1983 by Richard Conn
;       All Rights Reserved
;
;       ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;       The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;  RENAME Command --
;       RENAME is used to change the name of one or more files.  Unlike
; the ZCPR2-resident REN function, RENAME permits ambiguous file names
; and supports an Inspect mode that allows the user to confirm each
; rename before it is done.  Additionally, there is a Control Mode which
; allows the user to manually specify the name for each file as it is
; presented to him.
;
;       The RENAME command may be of the following forms:
;               RENAME dir:afn1=afn2,dir:afn3=afn4,... o
;               RENAME dir:afn,dir:afn1=afn2,... o
;       The first form shows elements of the form
;                       dir:afn1=afn2
; while the second form shows elements of the form
;                       dir:afn
; which is the same as
;                       dir:afn=afn
; and only makes sense if Control Mode is used.
;
;       The option characters (o) are none or more of the following:
;               C -- Control Mode; manually specify each new name
;               I -- Inspect and approve each rename
;               S -- Include SYStem files
;
;       Examples:
;               RENAME *.MAC=*.ASM      <-- Rename all ASM files to MAC
;               RENAME *.MAC C          <-- Rename all MAC files to names
;                                               input by the user
;               RENAME *.OBJ=*.COM SI   <-- Rename all COM files to OBJ
;                                               and include SYStem files
;                                               and Inspect and approve each
;                                               change
;

FALSE   EQU     0
TRUE    EQU     NOT FALSE

ESIZE   EQU     16      ; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE)

       EXT     DIRF    ; DIRECTORY PROCESSOR

       EXT     ZGPINS  ; INIT BUFFERS
       EXT     ZFNAME  ; FILE NAME PROCESSOR
       EXT     ZINIEXT ; EXTERNAL PATH INIT
       EXT     FNAME   ; FILE NAME PROCESSOR WITHOUT NAMED DIRS

       EXT     F$DELETE        ; DELETE FILE
       EXT     F$RENAME        ; RENAME FILE
       EXT     BBLINE  ; INPUT LINE EDITOR
       EXT     INITFCB ; INIT FCB
       EXT     BDOS    ; BDOS ENTRY
       EXT     RETUD   ; RETURN CURRENT USER/DISK
       EXT     PUTUD   ; SAVE CURRENT USER/DISK
       EXT     GETUD   ; RESTORE CURRENT USER/DISK
       EXT     MOVEB   ; COPY ROUTINE
       EXT     PHLDC   ; PRINT HL AS DECIMAL CHARS
       EXT     PRINT   ; PRINT ROUTINE
       EXT     COUT    ; CONSOLE OUTPUT ROUTINE
       EXT     CIN     ; CONSOLE INPUT ROUTINE
       EXT     CAPS    ; CAPITALIZE ROUTINE
       EXT     CRLF    ; NEW LINE ROUTINE
       EXT     FILLB   ; FILL ROUTINE
       EXT     CODEND  ; CODE END COMPUTATION ROUTINE

;
;  CP/M EQUATES
;
CPM     EQU     0       ; WARM BOOT
FCB     EQU     5CH     ; FCB
BUFF    EQU     80H     ; INPUT LINE BUFFER
CR      EQU     13      ; <CR>
LF      EQU     10      ; <LF>

;
;  Branch to Start of Program
;
       JMP     START

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;       This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
       DB      0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
       DW      40H     ; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
       DB      0,0     ; DISK, USER FOR FIRST PATH ELEMENT
                       ; DISK = 1 FOR A, '$' FOR CURRENT
                       ; USER = NUMBER, '$' FOR CURRENT
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0     ; DISK, USER FOR 8TH PATH ELEMENT
       DB      0       ; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
       DB      0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
       DW      0FF00H  ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
       DB      4       ; MAXIMUM NUMBER OF DISKS
MUSER:
       DB      31      ; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
       DB      0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
       DB      0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
       DB      10      ; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
       DB      'chdir',0       ; PASSWORD FOR MOVING INTO PRIV USER AREAS
       DS      41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
       DB      '$'     ; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
       DW      80H     ; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
       DW      00000H  ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
       DB      64      ; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
       DB      'NAMES   '      ; NAME OF DISK NAME FILE
       DB      'DIR'           ; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
       DB      0FFH    ; EXTERNAL PATH?
MCREQD:
       DB      0FFH    ; MULTIPLE COMMAND LINE?
MXREQD:
       DB      0FFH    ; MAX USER/DISK?
UDREQD:
       DB      0FFH    ; ALLOW USER/DISK CHANGE?
PUREQD:
       DB      0FFH    ; PRIVILEGED USER?
CDREQD:
       DB      0FFH    ; CURRENT INDIC AND DMA?
NDREQD:
       DB      0FFH    ; NAMED DIRECTORIES?
Z2CLASS:
       DB      0       ; CLASS 0
       DB      'ZCPR2'
       DS      10      ; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
START:
       LXI     H,0     ; GET STACK PTR
       DAD     SP
       SHLD    STACK   ; SAVE IT
       LXI     SP,STACK        ; SET SP
       CALL    PUTUD   ; SAVE CURRENT USER/DISK AWAY
       MVI     A,0FFH  ; SET DEFAULT USER
       STA     USER

       CALL    ZGPINS  ; INIT BUFFERS
       CALL    PRINT
       DB      'RENAME  Version '
       DB      VERS/10+'0','.',(VERS MOD 10)+'0',0
       LDA     FCB+1   ; GET FIRST CHAR OF FILE NAME
       CPI     ' '     ; NO FILE SPEC?
       JZ      HELP
       CPI     '/'     ; OPTION CAUGHT?
       JNZ     ECONT

;  PRINT HELP INFORMATION
HELP:
       CALL    PRINT
       DB      CR,LF,'RENAME Command --'
       DB      CR,LF,' RENAME dir:afn1=afn2,dir:afn3,dir:afn4=afn5,... o...'
       DB      CR,LF,LF,'d is disk, u is user, and o is one or more option '
       DB      'letters.'
       DB      CR,LF,'If one or more options are specified, the o MUST be '
       DB      'preceded by a space.'
       DB      CR,LF,'Nothing is required, and wild cards (?,*) are '
       DB      CR,LF,'permitted.  o is optional, and valid options are -'
       DB      CR,LF,' C -- Control Mode (Allow user to manually name each '
       DB      'file)'
       DB      CR,LF,' I -- Inspect Mode (Give user approval option)'
       DB      CR,LF,' S -- Include SYS files'
       DB      CR,LF,'dir: is a named directory or the form du:.'
       DB      CR,LF,'Named Directories are ',0
       LDA     NDREQD  ; NAMES REQUIRED?
       ORA     A       ; 0=NO
       JNZ     HELP1
       CALL    PRINT
       DB      'NOT ',0
HELP1:
       CALL    PRINT
       DB      'Permitted in this Version of RENAME'
       DB      CR,LF,'If u is omitted, current user is assumed, as with d.'
       DB      CR,LF,LF,'Special forms are:'
       DB      CR,LF,' RENAME dir: C   <-- Rename all files in named dir'
       DB      CR,LF,' RENAME du: C    <-- Rename all files in disk d, user u'
       DB      CR,LF,' RENAME u: C     <-- Rename all files in user u on '
       DB      'current disk'
       DB      CR,LF,' RENAME d: C     <-- Rename all files on disk d in '
       DB      'current user'
       DB      CR,LF,'Note that Control Mode was used above since a RENAME '
       DB      'of a file to itself'
       DB      CR,LF,'can be done, but is totally unnecessary.  Hence, '
       DB      'Control Mode allows a new name.'
       DB      0

;  RETURN TO OS
RETURN:
       LHLD    STACK   ; GET OLD STACK
       SPHL            ; SET IT
       RET

;  USER CHANGE NOT ALLOWED ERROR
UNOK:
       CALL    PRINT
       DB      CR,LF,'User Number Change Not Allowed -- Aborting',0
       JMP     RETURN

;  DISK CHANGE NOT ALLOWED ERROR
DNOK:
       CALL    PRINT
       DB      CR,LF,'Disk Change Not Allowed -- Aborting',0
       JMP     RETURN

;  PLACE ZERO AT END OF BUFFER
ECONT:
       LXI     H,BUFF  ; PT TO BUFFER
       MOV     A,M     ; GET COUNT
       INX     H       ; PT TO FIRST CHAR
       ADD     L       ; PT TO END OF BUFFER
       MOV     L,A
       MOV     A,H
       ACI     0
       MOV     H,A
       MVI     M,0

;  COPY BUFFER INTO TEMP BUFFER
       LXI     H,BUFF  ; PT TO BUFFER
       MOV     B,M     ; GET CHAR COUNT
       INX     H       ; PT TO FIRST CHAR
       INR     B       ; ADD ENDING 0
       LXI     D,CMDLNE        ; PT TO CMDLNE BUFFER
       CALL    MOVEB   ; COPY INTO COMMAND LINE BUFFER

;  EXTRACT FLAGS IF PRESENT
       XRA     A       ; SET NO INSPECT, NO R/O, AND NO SYSTEM FILES
       STA     INSPECT
       STA     CONTROL ; SET NO CONTROL MODE
       MVI     A,80H   ; SELECT NON-SYS FILES ONLY
       STA     SYSTEM
       LXI     H,0     ; SET FILE COUNT
       SHLD    FILECNT
       LXI     H,CMDLNE        ; PT TO BUFFER
;  SKIP TO FILE NAME STRING
SBLANK:
       MOV     A,M     ; SKIP TO NON-BLANK
       CPI     ' '     ; <SP>?
       JNZ     SBL1
       INX     H       ; PT TO NEXT CHAR
       JMP     SBLANK
;  SKIP TO END OF FILE NAME STRING
SBL1:
       MOV     A,M     ; SKIP TO <SP> OR EOL
       ORA     A       ; DONE?
       JZ      OPT
       CPI     ' '     ; <SP>
       JZ      OPT
       INX     H       ; PT TO NEXT
       JMP     SBL1
;  CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO
OPT:
       CPI     '/'     ; OPTION CHAR?
       JNZ     OPTION
       INX     H       ; SKIP SLASH
;  PROCESS LIST OF OPTIONS
OPTION:
       MOV     A,M     ; GET BYTE
       ORA     A       ; DONE?
       JZ      DSPEC
       INX     H       ; PT TO NEXT CHAR
       CPI     ' '     ; SKIP OVER SPACES
       JZ      OPTION
       CPI     '/'     ; IF OPTION LETTER, OBVIOUS ERROR, SO HELP
       JZ      HELP
       CPI     'C'     ; CONTROL?
       JZ      OPTCTRL
       CPI     'I'     ; INSPECT?
       JZ      OPTINS
       CPI     'S'     ; SYSTEM FILES?
       JNZ     HELP
       MVI     A,0C0H  ; SET FOR SYS FILES
       STA     SYSTEM
       JMP     OPTION
OPTCTRL:
       MVI     A,0FFH  ; CONTROL MODE
       STA     CONTROL
       JMP     OPTION
OPTINS:
       MVI     A,0FFH  ; INSPECT
       STA     INSPECT
       JMP     OPTION

;  EXTRACT DISK, USER, AND FILE NAME INFORMATION
DSPEC:
       LXI     H,CMDLNE-1      ; PT TO BEFORE FIRST BYTE
DSPEC0:
       INX     H       ; PT TO BYTE
       MOV     A,M     ; GET BYTE
       ORA     A       ; DONE?
       JZ      HELP
       CPI     ' '     ; <SP>?
       JZ      DSPEC0
;
;  MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS
;    HL PTS TO FIRST BYTE OF NEXT FILE SPEC
;
DSPEC1:
       CALL    GETUD   ; RESET USER IF NECESSARY
       LXI     D,NTFCB ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL

       PUSH    H       ; SAVE HL PTR
       CALL    CODEND  ; GET ADDRESS OF SCRATCH AREA
       MOV     B,H     ; ADDRESS IN BC
       MOV     C,L
       POP     H

       CALL    ZFNAME  ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER
       JZ      DERR    ; ERROR HANDLER

       SHLD    NEXTCH  ; SAVE PTR TO DELIMITER WHICH ENDED SCAN
       MOV     A,C     ; GET NEW USER
       STA     USER    ; SAVE IT
       MOV     A,B     ; SAVE POSSIBLE DRIVE SPEC
       CPI     0FFH    ; CURRENT DISK?
       JZ      USPEC
       LDA     MDISK   ; GET MAX DISK NUMBER
       DCR     B       ; ADJUST TO WITHIN BOUNDS 0-15
       CMP     B       ; WITHIN BOUNDS?
       MOV     A,B     ; GET DISK NUMBER IN A
       JNC     DSPEC2
DERR:
       CALL    PRINT
       DB      CR,LF,'Invalid Drive or User Specification',0
       JMP     RETURN

;  LOG IN SPECIFIED DISK
DSPEC2:
       PUSH    B       ; SAVE BC
       MOV     E,A     ; DISK NUMBER IN E
       LDA     DOK     ; OK TO DO SO?
       ORA     A       ; 0=NO
       JZ      DNOK    ; NOT ALLOWED ABORT
       MVI     C,14    ; LOG IN DISK
       CALL    BDOS
       POP     B       ; GET BC

;  CHECK FOR USER NUMBER
USPEC:
       MOV     A,C     ; GET NEW USER NUMBER
       CPI     0FFH    ; DEFAULT USER?
       JZ      NAME2
       CPI     '?'     ; ALL USERS NOT ALLOWED?
       JZ      UERR
       LDA     MUSER   ; GET MAX USER NUMBER
       CMP     C
       MOV     A,C     ; USER NUMBER IN A
       JNC     ULOG
UERR:
       CALL    PRINT
       DB      CR,LF,'Invalid User Number',0
       JMP     RETURN
ULOG:
       MOV     E,A     ; USER NUMBER IN E
       LDA     UOK     ; ALLOWED?
       ORA     A       ; 0=NO
       JZ      UNOK    ; DISALLOWED AND ABORT
       MVI     C,32    ; SELECT USER
       CALL    BDOS

;  FIRST NAME IS NOW EXTRACTED -- EXTRACT POSSIBLE SECOND NAME
NAME2:
       LXI     H,NTFCB ; PT TO FIRST NAME
       LXI     D,OFCB  ; PT TO FCB FOR 2ND NAME
       MVI     B,16    ; COPY 16 BYTES
       CALL    MOVEB
       LHLD    NEXTCH  ; PT TO CHAR WHICH ENDED PARSE
       MOV     A,M     ; GET IT
       CPI     '='     ; ASSIGNMENT?
       JNZ     RENAME  ; GO AHEAD IF NOT
       INX     H       ; PT TO CHAR AFTER '='

       PUSH    H       ; SAVE HL PTR
       CALL    CODEND  ; GET ADDRESS OF SCRATCH AREA
       MOV     B,H     ; ADDRESS IN BC
       MOV     C,L
       POP     H

       CALL    ZFNAME  ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER
       JZ      DERR    ; ERROR HANDLER

       SHLD    NEXTCH  ; SAVE PTR TO DELIMITER WHICH ENDED SCAN
       MOV     A,B     ; DISK OR USER NOT ALLOWED HERE
       ANA     C
       CPI     0FFH    ; MUST BE BOTH 0FFH
       JZ      RENAME
       CALL    PRINT
       DB      CR,LF,'Error -- 2nd Argument Contains Disk/User Spec',0
       JMP     RETURN

;  LOAD DIRECTORY AND RENAME FILES
RENAME:
       CALL    CODEND  ; PT TO END OF CODE
       CALL    RETUD   ; GET CURRENT USER
       LDA     SYSTEM  ; GET SYSTEM FLAG
       ORA     C       ; MASK IN SYSTEM FLAG TO USER
       LXI     D,OFCB  ; PT TO FCB
       CALL    INITFCB ; INIT THE FCB
       CALL    DIRF    ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE

;  REN DIR FILES; HL PTS TO FIRST FILE, BC=FILE COUNT
       CALL    RENFILES

;  CHECK FOR NEXT FILE SPEC
       LHLD    NEXTCH  ; GET PTR
       MOV     A,M     ; GET DELIM
       CPI     ','     ; ANOTHER FILE?
       JNZ     RENDONE
       INX     H       ; PT TO CHAR AFTER COMMA
       JMP     DSPEC1  ; CONTINUE PROCESSING

;  RENAME COMPLETE -- PRINT COUNT AND EXIT
RENDONE:
       CALL    PRCOUNT ; PRINT FILE COUNT
       JMP     RETURN

;  RENAME SELECTED FILES
RENFILES:
       MOV     A,B     ; CHECK FOR ANY FILES LOADED
       ORA     C
       RZ

;  PRINT FILE NAME
RENLP:
       PUSH    B       ; SAVE ENTRY COUNT
       CALL    PRINT
       DB      CR,LF,'Rename ',0
       PUSH    H       ; SAVE PTR TO FCB
       LXI     H,NTFCB ; COPY NEW TEMPLATE INTO RENFCB
       LXI     D,RENFCB
       MVI     B,16
       CALL    MOVEB
       POP     H       ; GET PTR
       PUSH    H       ; SAVE PTR
       INX     H       ; PT TO FN OF OLD NAME
       INX     D       ; PT TO FN OF RENFCB
       MVI     B,11    ; 11 BYTES TO FN AND FT
RENLP1:
       LDAX    D       ; GET CHAR OF NEW
       CPI     '?'     ; CHANGE '?' TO OLD CHAR
       JNZ     RENLP2
       MOV     A,M     ; GET OLD CHAR
       ANI     7FH     ; MASK OLD CHAR
       STAX    D       ; STORE IT AWAY AS NEW
RENLP2:
       INX     H       ; PT TO NEXT CHAR
       INX     D
       DCR     B       ; COUNT DOWN
       JNZ     RENLP1
       LXI     H,RENFCB        ; PT TO NEW NAME
       CALL    PRFN    ; PRINT FILE NAME
       CALL    PRINT
       DB      ' from ',0
       POP     H       ; GET PTR TO OLD FILE NAME
       PUSH    H       ; SAVE IT AGAIN
       CALL    PRFN    ; PRINT FILE NAME
       POP     H       ; GET PTR

;  CHECK FOR CONTROL MODE AND PERFORM CONTROL FUNCTION IF SET
       LDA     CONTROL ; GET FLAG
       ORA     A       ; NZ=YES
       JNZ     RENCTRL

;  CHECK FOR INSPECTION AND INSPECT IF SET
       LDA     INSPECT ; GET FLAG
       ORA     A       ; 0=NO
       JZ      DOIT

;  PROMPT USER FOR RENAME
       CALL    RENQ    ; REN QUESTION
       CPI     'Q'     ; QUIT?
       JZ      QUIT
       CPI     'Y'     ; YES?
       JZ      DOIT

;  DON'T RENAME FILE
NODO:
       CALL    PRINT
       DB      CR,LF,' ++ NO Name Change ++',0
       JMP     RENTEST

;  PRINT FILE NAME PTED TO BY HL
PRFN:
       INX     H       ; PT TO FILE NAME
       MVI     B,8     ; PRINT NAME
       CALL    PRNT
       MVI     A,'.'   ; DECIMAL
       CALL    COUT
       MVI     B,3     ; PRINT TYPE
       CALL    PRNT
       RET

;  PROMPT USER FOR RENAME
RENQ:
       CALL    PRINT   ; PRINT PROMPT
       DB      ' -- Rename (Y/N/Q=Quit/other=N)? ',0
       CALL    CIN     ; GET RESPONSE
       CALL    CAPS    ; CAPITALIZE
       CALL    COUT    ; ECHO
       RET

;  CONTROL FUNCTION -- ALLOW USER TO RENAME AS HE DESIRES
RENCTRL:
       PUSH    H       ; SAVE PTR TO FILE
RCTRL:
       CALL    PRINT
       DB      CR,LF,' -- New Name (<CR>=No Change)? ',0
       MVI     A,0FFH  ; CAPITALIZE
       CALL    BBLINE  ; INPUT LINE FROM USER
       ORA     A       ; CHECK FOR JUST <CR>
       JNZ     RCTRL0
       POP     H       ; GET PTR TO FILE
       JMP     RENTEST ; PROCEED WITH NEXT ENTRY
RCTRL0:
       LXI     D,RENFCB        ; PLACE INTO NEW NAME FCB
       CALL    FNAME   ; JUST EXTRACT NAME
       MVI     B,11    ; CHECK FOR ANY WILD CHARS
RCTRL1:
       INX     D       ; PT TO NEXT CHAR
       LDAX    D       ; GET IT
       CPI     '?'     ; CAN'T BE WILD
       JZ      WERR
       CPI     '*'     ; CAN'T BE WILD
       JZ      WERR
       DCR     B       ; COUNT DOWN
       JNZ     RCTRL1
       JMP     RDOIT   ; DONE -- PERFORM RENAME
WERR:
       CALL    PRINT
       DB      CR,LF,' Error -- Wild Card (?,*) in Name -- Try Again',0
       JMP     RCTRL

;  QUIT RENAME PROGRAM
QUIT:
       CALL    PRCOUNT ; PRINT COUNT OF FILES RENAMED
       CALL    PRINT
       DB      '  ++ QUIT -- Returning to CP/M ++',0
       JMP     RETURN

;  REN FILE, BUT GET PTR FIRST
RDOIT:
       POP     H       ; GET PTR

;  RENAME FILE; OLD NAME PTED TO BY HL, NEW NAME IN RENFCB
DOIT:
       PUSH    H
;  STEP 1 -- DETERMINE IF NEW NAME ALREADY EXISTS
       LXI     D,RENFCB        ; PT TO NEW NAME
       CALL    INITFCB
       MVI     C,17    ; SEARCH FOR FIRST
       CALL    BDOS
       INR     A       ; NOT FOUND?
       JZ      DOIT1
       CALL    PRINT
       DB      CR,LF,'         -- File Exists -- Delete It (Y/N/<CR>=N)? ',0
       CALL    CIN     ; GET RESPONSE
       CALL    CAPS
       CALL    COUT
       POP     H       ; PREP FOR ABORT
       CPI     'Y'     ; YES -- CONTINUE?
       JNZ     RENTEST ; NOT YES, SO SKIP IT
;  DELETE OLD FILE, SO SET ATTRIBUTES AND DO IT
       PUSH    H       ; SAVE PTR AGAIN
       CALL    INITFCB ; CLEAR FCB
       MVI     C,30    ; SET FILE ATTRIBUTES TO R/W IF NOT ALREADY
       CALL    BDOS
       CALL    INITFCB
       CALL    F$DELETE        ; DELETE FILE
DOIT1:
       POP     H       ; HL PTS TO OLD NAME
;  CLEAR THE OLD NAME'S ATTRIBUTES IN CASE IT WAS R/O
       PUSH    H       ; SAVE PTR TO OLD NAME
       LXI     D,OFCB  ; COPY OLD NAME
       MVI     B,16
       CALL    MOVEB
       PUSH    D       ; CLEAR ATTRIBUTES
       MVI     B,11    ; 11 BYTES
       INX     D       ; PT TO FIRST
DOIT2:
       LDAX    D       ; GET CHAR
       ANI     7FH     ; CLEAR ATT
       STAX    D       ; PUT CHAR
       INX     D       ; PT TO NEXT
       DCR     B       ; COUNT DOWN
       JNZ     DOIT2
       POP     D       ; NOW SET ATTRIBUTES OF OLD NAME
       CALL    INITFCB
       MVI     C,30    ; SET ATTRIBUTES
       CALL    BDOS
       CALL    INITFCB
;  DO THE RENAME
       LXI     H,RENFCB        ; PT TO NEW NAME
       XCHG
       CALL    INITFCB ; INIT NEW FCB
       XCHG            ; HL PTS TO NEW NAME, DE PTS TO OLD NAME
       CALL    F$RENAME        ; RENAME THE FILE
;  RESTORE THE ORIGINAL ATTRIBUTE BITS
       POP     H       ; GET PTR TO OLD NAME
       LXI
D,RENFCB+1      ; PT TO NEW NAME
       PUSH    H       ; SAVE PTR TO OLD NAME
       INX     H       ; PT TO FN OF OLD NAME
       XCHG            ; HL PTS TO NEW NAME, DE PTS TO OLD NAME
       MVI     B,11    ; 11 BYTES
DOIT3:
       LDAX    D       ; GET ATTRIBUTE BIT OF OLD NAME
       ANI     80H     ; LOOK ONLY AT ATTRIBUTE BIT
       ORA     M       ; MASK IN NEW NAME BYTE
       MOV     M,A     ; STORE IT AWAY
       INX     H       ; PT TO NEXT
       INX     D
       DCR     B       ; COUNT DOWN
       JNZ     DOIT3
;  SET THE ORIGINAL ATTRIBUTES INTO THE NEW FILE
       LXI     D,RENFCB        ; PT TO FCB
       CALL    INITFCB
       MVI     C,30    ; SET ATTRIBUTES
       CALL    BDOS
       LHLD    FILECNT ; INCREMENT FILE COUNT
       INX     H
       SHLD    FILECNT
       POP     H       ; GET PTR TO DIRECTORY ENTRY

;  PT TO NEXT ENTRY
RENTEST:
       LXI     D,ESIZE ; PT TO NEXT ENTRY
       DAD     D
       POP     B       ; GET COUNT
       DCX     B       ; COUNT DOWN
       MOV     A,B     ; CHECK FOR ZERO
       ORA     C
       JNZ     RENLP

;  RETURN TO CALLER
       RET

;
;  PRINT CHARS PTED TO BY HL FOR B BYTES
;
PRNT:
       MOV     A,M     ; GET CHAR
       CALL    COUT
       INX     H       ; PT TO NEXT
       DCR     B       ; COUNT DOWN
       JNZ     PRNT
       RET

;
;  PRINT COUNT OF NUMBER OF FILES RENAMED
;
PRCOUNT:
       CALL    CRLF    ; NEW LINE
       CALL    PRINT
       DB      CR,LF,'++ ',0
       LHLD    FILECNT ; GET COUNT
       MOV     A,L     ; CHECK FOR NONE
       ORA     H
       JZ      PRNO
       CALL    PHLDC   ; PRINT DECIMAL COUNT
       JMP     PRMS
PRNO:
       CALL    PRINT
       DB      'No ',0
PRMS:
       LHLD    FILECNT ; 1 FILE PROTECTED?
       MOV     A,H     ; HIGH ZERO?
       ORA     A
       JNZ     PRMULT
       MOV     A,L     ; LOW ONE?
       CPI     1
       JZ      PRSING
PRMULT:
       CALL    PRINT
       DB      ' Files Renamed ++',0
       RET
PRSING:
       CALL    PRINT
       DB      ' File  Renamed ++',0
       RET

;
;  BUFFERS
;
INSPECT:
       DS      1       ; INSPECT FLAG (0=NO, 0FFH=YES)
CONTROL:
       DS      1       ; CONTROL FLAG (0=NO, 0FFH=YES)
SYSTEM:
       DS      1       ; SYSTEM FLAG (0=NO, 80H=YES)
USER:
       DS      1       ; NEW USER, OR 0FFH IF NO CHANGE
NEXTCH:
       DS      2       ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE
FILECNT:
       DS      2       ; COUNT OF NUMBER OF FILES RENAMED
RENFCB:
       DS      40      ; FCB FOR RENAME
OFCB:
       DS      40      ; FCB FOR OLD FILE NAME AND OLD FILE TEMPLATE
NTFCB:
       DS      40      ; FCB FOR NEW FILE TEMPLATE
CMDLNE:
       DS      256     ; ALLOW MAX SIZE OF COMMAND LINE
       DS      100     ; STACK AREA
STACK:
       DS      2       ; OLD STACK PTR

       END