home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
ZDB18C.LBR
/
ZDB18SRC.LYR
/
ZDB18.Z80
< prev
next >
Wrap
Text File
|
1993-04-12
|
26KB
|
1,128 lines
;;; Mods by Al Hawley/Terry Hazen 02/05/92
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; * *
; * ZDB *
; * *
; * The Z-System Database *
; * Name/Address File Manager *
; * *
; * (C) 1990, 1991 by Joseph I. Mortensen *
; * *
; * *
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;
; Original Author: Joseph I. Mortensen
; 4214 Chelsea Ct.
; Midland, MI
; 517-835-6923
; Compuserve 70037,3161
; GEnie J.MORTENSEN3
; Ladera Z-Node
;
; Major Collaborator
; and Co-Author: Terry Hazen
;
; Assembler/Linker: ZMAC/ZML or Z80ASM/SLRNKP
;
; For documentation see ZDBxx.HLP
;
vers equ 18 ; version
suffix equ 'C' ; suffix character or ' ' if none
month equ 04 ; revision month
day equ 12 ; day
year equ 92 ; year
;
; the usual equates
;
ctrla equ 'A'-40h ; move cursor one word left
ctrld equ 'D'-40h ; move cursor right
ctrle equ 'E'-40h ; move cursor up one field
ctrlf equ 'F'-40h ; move cursor one word right
ctrlg equ 'G'-40h ; delete character
ctrlq equ 'Q'-40h ; quit add/edit without saving changes
ctrlr equ 'R'-40h ; refresh screen
ctrls equ 'S'-40h ; move cursor left
ctrlt equ 'T'-40h ; delete word right
ctrlv equ 'V'-40h ; insert character mode
ctrlw equ 'W'-40h ; quit add/edit and save changes
ctrlx equ 'X'-40h ; move cursor down one field
ctrly equ 'Y'-40h ; delete from cursor to end of field
;
bdos equ 05h
bel equ 07h
bs equ 08h
tab equ 09h
lf equ 0ah
ff equ 0ch
cr equ 0dh
esc equ 1bh
del equ 7fh
fcb equ 5ch
false equ 00h
true equ 0ffh
on equ true
lstat equ 15
;
; jthlib routines
.request jthlib
ext fnamz
;
; zplib routines
.request zplib
ext vprint,vpstr,gxymsg,gotoxy
;
; zslib routines
.request zslib
ext mdata1,binbcd
;
; dslip routines
.request dslib
ext timini,rclock
;
; vlib routines
.request vlib
ext stndout,stndend,at ;,gxymsg,vprint,vpstr
ext cls,ereol,gz3init,@ghl ;gotoxy
ext tinit,dinit,@goxy,curon,curoff,grxon,grxoff
;
; z3lib routines
.request z3lib
ext zsyschk,gzmtop,waitp1s
;
; syslib routines
.request syslib
ext fxo$open,fxo$close,fx$put
ext f$make,f$open,f$close,f$write,getfs
ext f$exist,r$write,r$read,setdma,mfn2,f$rename,f$delete
ext codend,condin,logud,bios ; fname,
ext isctrl,compb,acase3,ssbini,sort
ext capin,cin,cout,pa2hc,phldc,phlfdc,mafdc
ext lout,lcrlf,comphd,eval10,pout
;
; Program begins here
;
jp start
db 'Z3ENV' ; standard z3 header
db 1 ; type 1 program
z3addr: dw 0
;
; Bios printer ready check flag. Normally set to on (0ffh) to call the
; bios list status routine to check for printer ready. If your system
; hangs on a call to the bios list status routine, set this flag to 0:
;
pchkf: db on ; set to 0 to skip bios printer check
;
; Character used to terminate data fields
;
termf: db '<' ; char to terminate fields, 00h if none
;
; Default implied CFG filename at 010Dh for use with ZCFNG (8 characters):
;
db 'ZDB',vers/10+ '0',vers mod 10 + '0'
db suffix
db ' '
db 0 ; termination
;
; Default data file name (16 characters - fill unused positions with
; spaces):
; 'duu:filename.typ'
deffn: db 'ZDB.DTA ' ; default data file name
db 0 ; termination
;
;; Formfeed Flag -- set to zero for no form feed at end of label printing
;; session
;;ffflg: db on ; eliminated in V. 1.8
;
; Spare configuration patch space
;
ds 2 ; spare configuration patch bytes
;
; Printer string patches go here. Each string must have a length byte.
; Extra space is provided for longer printer codes. To eliminate any
; of these strings, make the first byte 0. The following are epson
; fx-85 compatible codes.
;
; Printer reset string, sent at start and end of each label/envelope
; printing session (4 characters maximum):
;
reset: db 2 ; length byte
db esc,'@' ; printer reset string
ds 2 ; extra space
;
; Set printer for printing return address. This string is sent to the
; printer after it is reset each time the return address is printed
; (12 characters maximum):
;
rin: db 7
db 0fh ; set condensed print
db esc,'x',1 ; set nlq mode
db esc,'p',1 ; set proportional print
ds 5 ; extra space
;
; Set printer for printing main address. Cancel any return address
; settings that may require it. Do NOT use reset, as it will cancel
; the label form length (12 characters maximum):
;
ain: db 9
db 12h ; cancel condensed print
db esc,'E' ; set emphasized print
db esc,'x',1 ; set nlq mode
db esc,'p',1 ; set proportional print
ds 3 ; extra space
;
; Set column for envelope address left margin:
;
lemarg: db 40 ; start address at column 40
;
; Set column for label address left margin:
;
llmarg: db 0 ; 0 for flush left
;
; Use return address in label (only if labels are large enough):
;
lra: db 0 ; 0 if no return address is desired
;
; Set number of lines per label (8 characters maximum):
;
labln: db 3
db esc,'C',6 ; set lines per label
ds 5 ; extra space
;
; Return address patch goes here. Space is provided for up to 80
; characters. If you plan on using a return address on your labels,
; add enough line feeds at the end of the return address to bring
; you to the first line of the label address. The rest of the
; line feeds required for an envelope are at 'addrsp'. For
; normal business size envelopes, the total number of line feeds
; must remain 14 and the string must be 0-terminated. To
; eliminate the return address, change retadr to a terminating
; null (00h) and put 14 line feeds at 'addrsp'.
;
retadr:
line1: db 'Joseph I. Mortensen'
db cr,lf
line2: db '4214 Chelsea Ct.'
db cr,lf
line3: db 'Midland, MI 48640'
db cr,lf,lf
;
; Pad the remainder of the address space with 0's
;
rept 80-($-retadr)
db 0
endm
;
; Space from return address to address. For normal business
; envelopes, the total number of line feeds in the return address
; and addrsp should be 14. If the number of line feeds in the
; return address -> first label address line is the normal three
; lines, addrsp should be set to 10 line feeds.
;
addrsp: db 10
;
; command line help message
;
hlpmsg: call vprint
db 'ZDB vers ',vers/10+ '0','.',vers mod 10 + '0'
db suffix
db ' Name/Addr Database'
db cr,lf
db ' Syntax: ZDB [[dir:]datafile.typ] ',cr,lf
dc ' Default datafile: '
ld hl,deffn ; display default filename
call vpstr
call vprint
dc cr,lf
jp exit2
;
; program starts here
;
start: ld (stack),sp
ld sp,stack ; set up internal stack
;
xor a
ld hl,data ; initialize data area
ld de,data+1
ld (hl),a
ld bc,datalen
ldir
;
ld hl,(z3addr) ; check for z3 system
call zsyschk
jp nz,exit2 ; not present, exit
call gz3init ; initialize vlib stuff
ld de,90h ; add TCAP offset from env
add hl,de ; and
ld (tcap),hl ; store it for use by edloop
call tinit ; initialize terminal
;
ld a,(fcb+1) ; check command tail
cp '/' ; asking for help?
jp z,hlpmsg ; yes, print help message
call gettim ; get the time
jr z,clkok ; if ok, jump
nclk: call noclk ; otherwise get date from manual entry
clkok: ld a,(fcb) ; get drive
call chkdrv
ld (fdrv),a ; store it
ld (datafil),a ; and in header
;
ld a,(fcb+13) ; get user for file
ld (fusr),a ; store it
;
; if no data file specified, use default datafile name
;
ld a,(fcb+1) ; check first filename character
cp ' '
jr nz,reopen ; filename specified
ld de,fcb ; no filename, use default
ld hl,deffn
call fnamz ; parse filename to fcb
jr clkok ;;;aeh
;
; after writing a new sorted file, program loops to reopen
;
reopen: ld a,(fusr) ; set user area for file
call setua
ld (fcb+12),a ; set extent to 0
ld (fcb+32),a ; likewise w/ current record
ld a,(fdrv)
sub a,41h
ld b,a
ld a,(fusr)
ld c,a
call logud
ld de,datafil+1 ; save user in header
call mafdc
ex de,hl
ld a,':'
ld (hl),a ; store colon
inc hl
push hl ; save header pointer
;
; open file
;
ld de,fcb
call f$exist ; check to see if it exists
jr nz,open
call f$make ; if not, create and open it
inc a
jp z,nogood
open: call f$open
jp nz,nogood
ld de,fcb+1 ; save original name in buffer
ld hl,nambuf
call mfn2
pop hl ; restore header pointer
call mfn2 ; save filename
;
ld de,fcb
call getfs ; get file size in records
ld (recs),hl
call frame ; do frame and screen layout
call index ; create index
;
ld hl,(recs) ; save it
ld a,h ; check for empty file
or l
jr nz,dotop ; not empty
;
doadd: call curtim ; display time and date
ld a,'A' ; empty file, so adding new record
jr menua ; is the only choice!
;
dotop: call firstr ; display first record and wait for cmd
;
menu: call clrmnu ; main menu line
db 1,'A=Add C=Call D=Del E=Ed F=Find X=Xfind <>=Prv/Nxt '
dc 'O=Outp I=Idx ^S=Sort'
call qquit
;
; main program loop
;
main: call curtim ; display current time & date
call at
db 24,79 ; position cursor at '?' in menu line
call getchar ; wait for command
menua: ld de,cmdtbl ; run command thro' command table
call acase3
jr main
;
; end of main loop
;
;
; command table
;
cmdtbl: db 18 ; no. of entries in command table
dw menu
db 'Q'
dw exit
db esc
dw exit
db 'A'
dw new
db 'E'
dw edit
db 'D'
dw delete
db 'F'
dw find
db ','
dw prev
db '<'
dw prev
db '.'
dw next
db '>'
dw next
db 'O'
dw output
db ctrlr ; ^r to refresh screen if it gets out of whack
dw refscr
db ctrls ; ^s for sort
dw asksrt
db 'I'
dw settyp
db 'T'
dw firstr
db 'X'
dw qfind
db 'B'
dw last
db 'C'
dw dial
;
; exit routines
;
exit: ld de,fcb
call f$close
call curon
call dinit
exit2: ld sp,(stack)
ret
;
; main subroutines
;
; screen display routines
;
frame: call curoff ; turn off cursor
call cls ; clear screen
call at ; do standout header
db 1,1
ld b,66 ; do standout bar
call pad
call at
db 2,1
call grxon
ld b,79
ld a,(@ghl)
frloop: call cout
djnz frloop
call at
db 23,1
ld b,79
frlp0: call cout
djnz frlp0
call grxoff
;
ld hl,panel
ld b,(hl) ; enter with hl=panel pointer
inc hl
;
scrnloop:
call @goxy
call vpstr
djnz scrnloop
ret
;
refscr: call frame ; refreshes entire screen
call currec
jp menu
;
; display current record number and total
;
bldisp:
currec: ld hl,(recptr)
call lhlhl ; get record number of current record
call divhl2 ; divide by 2
inc hl ; make it rel 1
currec0:call gxymsg
db 1,45,1,0
call phldc
call vprint
dc ' of '
ld hl,(recs) ; get total number of records
call divhl2 ; divide by 2
call phlfdc
call vprint ; terminate field and end standout
dc ' ',2
call clrdis ; and fall through to displa
;
; display current record
;
displa: ld hl,pospanel ; point to cursor position panel
ld de,fieldpanel ; point to field panel
ld b,(hl)
inc hl
displaloop:
call @goxy ; position cursor to field start
inc hl ; point to next field
call stndout
ex de,hl ; hl=field address
push hl ; save field address pointer
call lhlhl ; get field addr in hl
call vpstr ; display field
call stndend
pop hl
inc hl ; point to next field
inc hl
ex de,hl
djnz displaloop
;
newdat: call gxymsg ; displays date
db 3,66,1,0 ; date location
ld hl,datmod+1 ; get month
call paslsh
inc hl ; get day
call paslsh
dec hl
dec hl ; get year
ld a,(hl)
call pa2hc
jp stndend
;
divhl2: srl h ; divide hl by 2, result in hl
rr l
ret
;
curtim: call gxymsg ; displays current date and time
db 1,63,1,0
ld hl,today+1
call paslsh
inc hl
call paslsh
dec hl
dec hl
ld a,(hl)
call pa2hc
call gettim
jr nz,notime
ld a,' '
call cout
inc hl
inc hl
inc hl
ld a,(hl)
call pa2hc
ld a,':'
call cout
inc hl
ld a,(hl)
call pa2hc
notime: jp stndend
;
gettim: call timini ; see if there is a clock
jr nz,clkfnd
inc a
ret
clkfnd: push hl
ld hl,today ; point to clock buffer
call rclock
pop hl
ret
;
paslsh: ld a,(hl)
call pa2hc ; print date with slash
ld a,'/'
jp cout
;
; fill record display fields with blanks
;
clrdis: ld hl,pospanel ; point to cursor position panel
ld b,(hl)
inc hl
clrloop:
call @goxy ; position cursor to field start
push bc ; save count
ld b,(hl) ; get field length
call pad ; pad field with blanks
pop bc ; restore count
inc hl ; point to next field
djnz clrloop
ret
;
;
; routines for adding, editing, and deleting records
;
edit: xor a ; edit existing data record
ld (newflg),a
call decfptr
call edita
jp wrecs ; write data record and resort index
;
new: ; adding a new record
call chkmem ; check to see if enough memory left
jp c,nomem ; out of memory, jump to out of memory message
call clrdis ; ok, continue
call iniblk ; initialize edblk
ld a,true ; set "new" flag
ld (newflg),a
;
edita: ld hl,today ; get date from "today"
ld de,datmod ; and move to datmod
ld bc,3
ldir
call newdat ; get the date and display it
call clrmnu
db 1,'^X/TAB/RET=nxt fld ^E=prv fld ^S/^D=char l/r'
dc ' ^Y=era cursor rt ESC=exit',2
;
edfields:
ld hl,pospanel ; point to cursor position panel
ld de,fieldpanel ; point to field address panel
ld b,(hl) ; number of fields
inc hl
;
efloop: ld a,(hl) ; save row position
ld (lpos),a
call @goxy ; position cursor
push bc ; save count
ld b,(hl) ; get field length
dec hl ; save column position
ld a,(hl)
ld (cpos),a
inc hl ; point to next field
inc hl
ex de,hl ; hl=field address
push hl
call lhlhl ; get field pointer in hl
push de
call edloop ; edit field
pop de
pop hl
inc hl ; point to next field address
inc hl
ex de,hl ; hl=next field cursor position
pop bc
cp esc ; quit edloop?
jr z,term ; yes, go to end
cp ctrlw ; ^W same as esc
jr z,term
cp ctrlq ; ^Q to quit without saving edit
jr z,term
cp ctrle ; if ^e, go to previous field
jr z,prevf
djnz efloop ; else do next field
jr term ; done
;
prevf: or a ; clear carry
push bc ; save count
ld bc,6 ; back up to previous field cursor pos
sbc hl,bc
ex de,hl
ld bc,4 ; back up to previous field
sbc hl,bc
ex de,hl
pop bc ; restore count
inc b ; back up one field
ld a,(pospanel) ; get number of fields
cp b ; test for first field
jr nc,efloop ; loop or fall thru if past first field
;
term: push af
call delins ; delete insert msg
pop af
cp ctrlq ; exit without saving?
jr nz,term1
;
ld a,(newflg) ; editing an existing record?
or a
jr nz,xadd ; add abort
pop hl ; if edit abort, discard return address
jr xedit
xadd: call ckdel ; quit if no non-deleted records
call decfptr ; if add abort, back up one
xedit: call current ; redisplay current record
jp menu
;
term1:
call clrmnu
dc 1,'TAB=restart/[SAVE] ?',2,bs
call cin
cp tab
jp z,edita
call curoff ;;;jth
ld a,(newflg) ; editing an existing record?
or a
ret z ; yes, we're done here
;
ld hl,(recs) ; get number of index records
ld (xfptr),hl ; save it for updinx and to
ld (fptr),hl ; keep track of appended records
ld hl,(n)
ld (count),hl ; save number of index records
call rwrtblk
call updinx ; add new key to index table
call inxsrt ; rebuild order table and sort index
ld hl,(recs) ; increment record count
inc hl
inc hl
ld (recs),hl
;
call clrmnu
dc 1,'Add another record? [Y]/n ?',2,bs
call getchar
cp 'N'
jp nz,new
;
; since the index may have been resorted and we only know the
; current fptr, we need to find the corresponding recptr to properly
; redisplay the current record at its new location in the index
;
getrp: call decfptr ; back up one
getrp0: ld hl,(first) ; start of index
ld de,14 ; record number offset
;
recplp: add hl,de ; hl=recptr
push hl ; save recptr
call lhlhl ; hl=fptr for index record
ld de,(fptr) ; de=fptr
call comphd ; does this record have the right fptr?
pop hl ; restore recptr
ld de,16 ; offset to next
jr nz,recplp ; not this index record, check next
ld (recptr),hl ; save record pointer
call current ; display record
jp menu
;
; write 256 bytes to random record
;
rwrtblk:ld hl,edblk
call rwrite ; write new record
ld hl,edblk1
jp rwrite
; delete record
;
delete:
call clrmnu
dc bel,1,'Are you sure? y/[N] ?',2,bs
call getchar
cp 'Y'
jp nz,menu
;
ld a,'D'
ld (newflg),a
call iniblk ; fill current record w/ nulls
ld hl,edblk
ld (hl),on ; make first byte 0ffh
call decfptr ; decrement file record
;
wrecs: call rwrtblk ; write 256 bytes to file
ld hl,(recptr) ; get record pointer
ld de,14
sbc hl,de ; back up to index pointer
ex de,hl ; pointer in de for movkey
call movkey ; update index key
ld de,ssb
call sort ; sort index
;
ld a,(newflg) ; deleting a record?
cp 'D'
jp nz,getrp ; exit from edit, so get record pointer
call ckdel ; quit if no non-deleted records
call next
jp menu
;
; file movement routines
;
; find and display next record
;
next: call ckeoi ; check for end of index
jr nz,oknxt ; not eoi
;
firstr: call gotop ; set pointer to beginning of file
current:call rread ; read current record
jr ckrec
;
oknxt: call riread ; increment pointers, read next record
ckrec: call delrec ; check for deleted record
jp nz,bldisp ; ok, display it
jr next ; deleted, so get next record
;
; move to and display last record
;
last: ld hl,(xrecptr) ; get last index record pointer in hl
call savptr
jr current
;
; move to and display previous record
;
prev: call backup ; move pointer back
call rread ; read a record
ld hl,edblk ; check first byte to see if it's a
ld a,(hl) ; valid record. 0ffh = deleted record.
inc a
jr z,prev ; if deleted, try the previous one
jp bldisp
;
; get first index record number
;
gotop: ld hl,(first) ; get start of index table
getpt0: ld de,14 ; offset to record number
getptr: add hl,de
savptr: ld (recptr),hl ; save record pointer
call lhlhl
ld (fptr),hl ; save record number
ret
;
; back up to previous record
;
backup: ld hl,(recptr) ; get current index record
or a ; clear carry
ld de,16 ; back up one index record
sbc hl,de ; get new record pointer
ld de,(first) ; check if past first
call comphd
jr nc,savit
ld hl,(xrecptr) ; point to last record pointer
savit: jr savptr ; save pointers
;
; Increment record pointers
;
mvrptr: call ckeoi ; check for end of index table
jr z,gotop ; yes, start over
;
mxrptr: ld hl,(recptr) ; get index record pointer
ld de,16 ; point to next
jr getptr
;
; get contents of hl in hl
;
lhlhl: ld a,(hl) ; get record number
inc hl
ld h,(hl)
ld l,a
ret
;
; decrement record pointer
;
decfptr:ld hl,(fptr)
dec hl
dec hl
ld (fptr),hl
ret
;
; search routines. uses a revised 'scanner' from syslib which eliminates
; case sensitivity. QFIND uses an index in RAM to find file pointers for
; last names or zip codes, depending on which index is selected. FIND
; runs through the file, top to bottom, to do its search.
;
scanner:
; main loop
;
scan: ld a,b ; done if b<c
cp c ; done?
ret c
;
; scan hl for de for c bytes
;
push bc ; save registers
push de
push hl
;
scanl: ld a,(de) ; get field byte
cp 'a' ; capitalize if necessary
jr c,scanx
cp 'z'+1
jr nc,scanx
and 05fh
scanx: cp (hl) ; compare with search string character
jp nz,nexthl ; no match
;
scan2: inc de ; pt to next
inc hl
dec c ; count down
jp nz,scanl
;
; match
;
pop hl ; restore registers
pop de
pop bc ; old bc
ret ; zero flag is set
;
; not found yet
;
nexthl: pop hl ; restore registers
pop de
pop bc ; get count
inc de ; point to next in scanned vector
djnz scan ; continue scanning
;
; no match!
;
not$found:
or 0ffh
ret
;
keeplk:
call clrmnu
dc 1,'Continue search? y/[N] ?',2,bs
call getchar
cp 'Y'
ret z
cp 'C' ; also allow C for continue
ret
;
; Express search routine
;
qfind: call getkeyf
ld hl,(first) ; point to index base address
ld (inxptr),hl ; store in index pointer
ld de,(count) ; get count
dec de ; subtract one
ld (xcount),de ; save it
;
qloop:
push bc ; save c=length of search string
ld b,14 ; b=length of index key first/last names
ld de,srch ; get search string
push hl ; save index pointer
ex de,hl
call scanner ; scan the target
pop hl ; restore index pointer
jr nz,nomatch ; jump if no match
call getpt0 ; get file pointer
call rread ; read the record
call bldisp ; display it
call keeplk ; keep looking?
jr z,nomatch
pop bc
jp menu
;
nomatch:pop bc
ld de,(xcount) ; get count of records
ld a,d
or e ; zero? quit if xcount = 0
jr z,nofind ; no, go again
;
dec de
ld (xcount),de ; decrement record count
ld hl,(inxptr) ; increment index pointer
ld de,16
add hl,de
ld (inxptr),hl ; save new pointer
jr qloop
;
; scans the entire record for a match
;
find: call getkeyf
ld hl,0 ; set to top of file
ld (fptr),hl
;
rloop: ; check for end of file
ld hl,(recs)
ld de,(fptr)
call comphd
jr nz,okgo
;
nofind: call clrmnu
dc bel,1,'Not Found....Press Any Key',2
call cin
call firstr
jp menu
;
okgo: call rread ; b=no. of bytes to search
push bc
ld b,253 ; c=length of target
ld hl,srch ; hl points to search string
ld de,edblk ; de points to target
call scanner ; scanner does the job
jr nz,lloop ; z=match
ld hl,(fptr) ; get file pointer
call divhl2 ; divide by 2
call currec0 ; display record
call keeplk ; continue search?
jr nz,loopnd ; no, quit
lloop: pop bc ; yes, go on
jr rloop
;
loopnd: pop bc
jp getrp
;
; sort routines
;
; set index type ; do index type as toggle function
;
settyp: ld a,(srttyp) ; get original type
or a ; is it null (name)?
cpl ; toggle it
ld (srttyp),a ; Save new type
ld hl,lntyp ; name index msg
jr nz,set0 ; zip, make name
ld hl,ziptyp ; zip index msg
set0: ld de,inxtyp ; move index type to header message
ld bc,9
ldir
ld hl,inxmsg ; point to index message
call @goxy ; position cursor
call vpstr ; display message
call index ; do new index
jp firstr ; and display new first record
;
; create index
;
index: call codend ; get end of code
ld (order),hl ; save in ssb as start of order table
ld (first),hl ; and as address of first record
ld hl,0 ; start with first file record
ld (fptr),hl
ld (count),hl ; zero the counter
;
inxlp: ld hl,(recs) ; get number of records
ld de,(fptr) ; check for end of file
call comphd
jr z,inxsrt ; we're done, so sort index
;
ex de,hl
ld (xfptr),hl ; save it as last record
call rread ; read next record and increment pointer
call updinx ; update index
jr inxlp ; repeat until done
;
; Add new record to index table
;
updinx: ld de,(order) ; point to end of index table
call movkey ; add key
ld (xrecptr),de ; save last record number pointer
ld hl,xfptr
ld bc,2 ; move record number to index
ldir
ld (order),de ; save start of next index entry
;
inccnt: ld hl,(count) ; bump counter
inc hl
ld (count),hl
ret
;
; create sorted index
;
inxsrt: ld hl,(count) ; get count
ld (n),hl ; store in ssb as total
ld hl,(order) ; pointer to end of index table
ld de,ssb ; pointer to ssb
call ssbini ; create order table
jp sort ; sort index
;
; Add new key to index table.
; On entry, de points to start of next index entry
;
movkey: ld a,(srttyp) ; check index type
or a ; zip?
jr nz,movzip ; yes
;
ld hl,lname ; de automatically increments in hmovb
ld bc,9 ; index on first 9 bytes of lname
ldir
ld hl,fstnm
mov5: ld bc,5 ; then on first 5 bytes of fstnm
ldir
ret
;
movzip: ld hl,zip
ld bc,9 ; index on 9 zip bytes
ldir
ld hl,lname ; then on first 5 bytes of last name
jr mov5
;
; Ask if we want to write sorted file
;
asksrt:
call clrmnu
dc 1,'Write Sorted File? y/[N] ?',2,bs
call getchar
cp 'Y'
jp nz,menu
call dwf ; display writing file message
ld hl,srtfnm ; get sort file name into its fcb
ld de,srtfcb
call fnamz ;fname
ld a,(fusr) ; get user for file
ld (sfusr),a ; store it
ld a,(srtfcb) ; get drive
call chkdrv
ld (sfdrv),a ; store it
ld a,(sfusr) ; set user area for file
call setua
ld (srtfcb+12),a ; set extent to 0
ld (srtfcb+32),a ; likewise w/ current record
ld de,srtfcb ; open sort output file
call f$make
jp nz,nogood
ld hl,0
ld (count),hl ; zero the count
call gotop ; get starting record number
;
getrec: call rread ; read record
call mxrptr ; increment pointers
ld hl,edblk
call setdma
ld a,(hl) ; skip deleted records
inc a ; if first byte = 0ffh it's an erased
jr z,nowrt ; record.
ld de,srtfcb ; write a record
call f$write
ld hl,edblk1
call setdma
ld de,srtfcb
call f$write ; write a record
nowrt: call inccnt ; increment the count
ld de,(n)
call comphd
jr nz,getrec
;
finsrt: ld de,srtfcb ; close sorted file
call f$close
ld de,fcb ; close original file
call f$close
;
ld de,bakfcb ; check to see if there's a previous
ld hl,bakfil ; backup file
call fnamz ; fname
call f$delete
;
ld de,fcb ; give original file the name
ld hl,bakfcb ; 'backup.dta'
call f$rename
;
ld de,fcb ; put original file name back into
ld hl,nambuf ; fcb
call fnamz ; fname
ex de,hl ; rename the sorted file with the
ld de,srtfcb ; original file name
call f$rename
;
jp reopen ; reopen the newly sorted file
;
; compare de.vector to hl.vector for b bytes
; return C if de.vector < hl.vector
;
compv: ex de,hl
ld b,16
call compb
ex de,hl
ret
;
; file split in two because of ZDE's
; memory limitations
include zdb18.a ; remainder of source code
include zdb18.b ; phone dialer module
include zdb18.d ; data area
end