title WSDEL - WordStar Code Deletion name ('WSDEL') maclib base80 ; WSDEL deletes some codes in a WordStar file generating ; a pure ASCII file. Call it: ; ; WSDEL WORDSTAR_FILE[.WS] [ASCII_FILE[.ASC]] ; ; Copyright (c) Werner Cirsovius ; Hohe Weide 44 ; 20253 Hamburg ; Phone:(+49)40/4223247 ; ; Version 2.1 Oktober 1995 entry $memry ext cmdarg,comp3,wcard,adda,strcn0,fildrv ext add32,dout32,parse,srcfrs,srcnxt ext rdfcb,rdbuf,rdbfp,wrfcb,wrbuf,wrbfp ext open,creatd,close,closef,delete,geteof,dskput $PRG$ macro db 'WSDEL' endm ARGMX equ 2 _PRGN equ 0 _STRG equ _PRGN+1 _PRFST equ _STRG+1 _PRFCB equ _PRFST+1 _PRDST equ _PRFCB+1 _PRSRC equ _PRDST+1 _EOT equ -1 _SF equ 0 dseg ExeTab: dw ExePRGN,ExeSTRG,ExePRFST,ExePRFCB,ExePRDST,ExePRSRC illcallp: db _PRGN db _STRG dw $ILLCALL db _EOT illparsep: db _PRGN db _STRG dw $ILLPARSE db _EOT samenerrp: db _PRGN db _STRG dw $ILLSAME db _EOT illwildp: db _PRGN db _STRG dw $ILLWILD db _PRFST db _EOT nofile: db _PRGN db _STRG dw $ILLSRC db _PRSRC db _EOT illsrcp: db _PRGN db _STRG dw $ILLSRC db _PRFCB db _EOT illdstp: db _PRGN db _STRG dw $ILLDST db _PRFCB db _EOT wrerrp: db _PRGN db _STRG dw $WRERR db _PRDST db _EOT ClsErrp: db _PRGN db _STRG dw $CLSERR db _PRDST db _EOT $PRGNAM: db cr,lf $PRG$ db null $ILLCALL: db ' deletes some codes in a WordStar file generating' db cr,lf db 'a pure ASCII file. Call it:' db cr,lf,lf db tab $PRG$ db ' WORDSTAR_FILE[.WS] [ASCII_FILE[.ASC]]' $CRLF: db cr,lf,null $ILLPARSE: db ': Invalid file specification' db cr,lf,null $ILLSAME: db ': Must be different files' db cr,lf,null $ILLWILD: db ': Invalid wildcard in file name ' db null $ILLSRC: db ': Cannot find file ' db null $ILLDST: db ': Cannot create file ' db null $WRERR: db ': Write error on file ' db null $CLSERR: db ': Cannot close file ' db null $NOFILE: db 'No file created' db cr,lf,null $FRDY: db '[' $FSRC: db '12345678.123 -> ' $FDST: db '12345678.123',null $RDY: db ']' db cr,lf,'Conversion done with',null $NOCNV: db 'out' X$RDY: db ' deletions',null $WITH: db ' ',null $CHG: db ' characters were changed',null $DONE: db cr,lf db 'Ready' db cr,lf,null ARGV: ds 2*ARGMX $memry: ds 2 PB: ds 2+2 DecASCII: ds 2 HEAP: ds 2 $ASC: db '.' $$ASC: db 'ASC',null ASClen equ $-$ASC $$WS: db 'WS ' $$CTRL: db tab,lf,cr CtrlLen equ $-$$CTRL ; ; Flag state: ; ; Bit 0 : Only one file selected ; Flag: ; \ db 00000000b ; | Drv: ; | ds 1 ; / ; cntint: ; \ db 0,0,0,0 ; | cntmsb: ; | db 0,0,0,0 ; / one: db 0,0,0,1 FCNT: dw 0 FPTR: ds 2 cseg ; ; Print resulting number ; prnum: ld de,(DecASCII) push de ld b,null call dout32 ; Convert to ASCII pop de call strcn0 ; Print it ret ; ; Test result count zero ; isallzero: call is.c.zero ; Test changed count ret nz ; If so, test deleted count ; is.d.zero: ld iy,cntint jr tst0 is.c.zero: ld iy,cntmsb tst0: ld a,(iy+0) or (iy+1) ; Simple test or (iy+2) or (iy+3) ret ; ; Increment changed character count ; incmsb: ld bc,cntmsb jr inc... ; ; Increment deleted character count ; incchr: ld bc,cntint inc...: push de push hl ld h,b ld l,c ld de,one call add32 ; Add 1 to it pop hl pop de ret ; ; Initialize the program ; iniWSDEL: ld ix,Flag ; Point to flag call inimem ; Set up memory ld hl,ARGV ld de,CCP ld b,ARGMX call cmdarg jp c,illcall ; Invalid number of arguments cp ARGMX-1 ; Test only one parameter call z,Bld2File ; Prepare 2nd file ld hl,(ARGV) ; Get 1st argument ld de,(rdfcb) ; Get source FCB ld bc,$$WS call getFCB ; Convert it ld hl,(ARGV+2) ; Get 2nd argument ld de,(wrfcb) ; Get destination FCB ld bc,$$ASC call getFCB ; Convert it ld hl,(rdfcb) ; Get source FCB ld de,(wrfcb) ; Get destination FCB ld c,.fdrv+.fname+.fext call comp3 ; Verify not same FCBs ret nz jp samenerr ; ; Initialize memory ; inimem: ld hl,($memry) ; Get first free address ld (rdbuf),hl ; Set for source buffer ld de,reclng add hl,de ld (wrbuf),hl ; Set for destination buffer add hl,de ld (rdfcb),hl ; Set for source FCB ld de,FCBlen add hl,de ld (wrfcb),hl ; Set for destination FCB add hl,de ld (DecASCII),hl add hl,de ld (HEAP),hl ; Set for heap ret ; ; Prepare 2nd file ; Bld2File: ld hl,(ARGV) ; Get 1st argument ld de,(HEAP) ld (ARGV+2),de ; Put new into 2nd argument call cpyASC ; Unpack text file ld (HEAP),de ret ; ; Copy main file ^HL to ^DE for .ASC ; cpyASC: ld a,(hl) or a ; Test end jr z,EndCpy ; Yeap cp '.' ; Test delimiter jr z,EndCpy ; Also end ld (de),a ; Unpack name inc hl inc de jr cpyASC EndCpy: ld hl,$ASC ld bc,ASClen ldir ; Unpack .ASC set _SF,(ix+0) ; Indicate single file ret ; ; Get FCB ^DE from name ^HL and exclude wild cards ; Default extension in reg ^BC ; getFCB: ld (PB),hl ; Save name ld (PB+2),de ; Save FCB push de ld de,PB call parse ; Parse file pop de jp c,illparse ; Invalid file format call setdefext ; Set default extension bit _SF,(ix+0) ; Test single file call z,wcard ; Verify no wild card if not ret nz jp illwild ; ; Set default extension ; setdefext: ld hl,.fdrv+.fname add hl,de ; Point to extension ld a,(hl) ; Get it cp ' ' ; Test blank ret nz ; Nope push de ex de,hl ld l,c ld h,b ld bc,.fext ldir ; Unpack it pop de ret ; ; Open existing file ; r.open: ld a,reclng ld (rdbfp),a ; Prepare read ld de,(rdfcb) ; Get FCB call open ; Open file ret nc jp illsrc ; ; Open new file ; w.open: xor a ld (wrbfp),a ; Prepare write ld de,(wrfcb) ; Get FCB call creatd ; Create file ret nc jp illdst ; ; Get character from file ; fget: call geteof ; Get it ret ; ; Put character to file ; fput: ld b,a ; Save character call dskput ; Put it jp c,wrerr ; Error inc e ; Advance column ld a,b ; Get character cp ' ' ; Test control ret nc ; Nope cp tab ; Filter tabulator ret z ld e,0 ; Clear column ret ; ; %% ERROR ROUTINES %% ; NoFileFnd: ld ix,nofile jr Domess illcall: ld ix,illcallp jr Domess illparse: ld ix,illparsep jr Domess samenerr: ld ix,samenerrp jr Domess illwild: ld ix,illwildp jr Domess illsrc: ld ix,illsrcp jr Domesst illdst: ld ix,illdstp Domesst: ld (PB+2),de jr Domess wrerr: ld ix,wrerrp jr Domess ClsErr: ld ix,ClsErrp ; ; Process complexe message output from control table ; Domess: ld a,(ix) ; Get control inc a ; Test end of table jp z,OS ; Yeap ld hl,ExeTab-2 call idxtab ; Get address from table inc ix call reg ; Execute routine jr Domess ; ; Get address from table ; idxtab: push de add a,a ; Double index call adda ; Point into table ld e,(hl) ; Fetch execution address inc hl ld d,(hl) ex de,hl pop de ret ; ; Simple subroutine jumps to ^HL ; reg: jp (hl) ; ; Control 0: Print name of program ; ExePRGN: ld de,$PRGNAM call strcn0 ret ; ; Control 1: Print string in table ; ExeSTRG: ld e,(ix+0) ; Fetch string pointer ld d,(ix+1) inc ix inc ix call strcn0 ret ; ; Control 2: Print name of file from string ; ExePRFST: ld de,(PB) ; Get name call strcn0 ; Print it jr crlf ; ; ; Control 5: Print name of file from read FCB ; ExePRSRC: ld de,(rdfcb) ; Get FCB jr prExec4 ; ; Control 3: Print name of file from parse FCB ; ExePRFCB: ld de,(PB+2) ; Get FCB prExec4: call fildrv ; Print it crlf: ld de,$CRLF call strcn0 ret ; ; Control 4: Print name of destination file from FC and delete it ; ExePRDST: ld de,(wrfcb) ; Get FCB call close ; Close it call delete ; Then delete it call prExec4 ; Finally print it ld de,$NOFILE call strcn0 ; Tell no success ret ; ; %%%%%%%%%%%%%%%%%%%%%%%% ; IllCPU: ld de,$ill.CPU ld c,.string call BDOS ; Print error message jp OS ; dseg $ill.CPU: $PRG$ db ' requires Z80 CPU',eot ; cseg ; ; %%%%%%%%%%%%%%%%%%%%%%%% ; %%% Entry of program %%% ; %%%%%%%%%%%%%%%%%%%%%%%% ; WSDEL: ld sp,(TPATOP) ; Get my stack call iniWSDEL ; Init program call SampleFiles ; Build list of files ld hl,(FCNT) ; Get file count ld a,l or h ; Verify at leas one file jp z,NoFileFnd FileLoop: call ProcFile ; Process one file jr nc,FileLoop ; Go on ld de,$DONE call strcn0 ; Give final message jp OS ; ; Build list of files ; SampleFiles: ld hl,(HEAP) ld (FPTR),hl ; Init file pointer ld de,(rdfcb) ; Get FCB ld a,(de) ; Get drive ld (ix+1),a ; Save it push hl call srcfrs ; Find file SampleNext: pop de ld (HEAP),de ret c ; End of file ld a,(ix+1) ld (de),a ; Set drive inc de ld b,.fname call doCpy1 ; Unpack name and extension ld b,.fext call doCpy ld hl,(FCNT) inc hl ; Update count ld (FCNT),hl push de call srcnxt ; Find next jr SampleNext ; ; Copy name of file ; Cpname: ld hl,(rdfcb) ; Get source FCB ld de,(wrfcb) ; Get destination FCB ld bc,.fdrv+.fname ldir ; Unpack it ret ; ; Copy name and extension of file ; cpyFN: ld b,.fname call doCpy inc de ld b,.fext doCpy: inc hl doCpy1: ld a,(hl) and NoMSB ld (de),a inc de djnz doCpy ret ; ; Test valid control - Z set says yes ; isValidCtrl: ld hl,$$CTRL ld bc,CtrlLen cpir ; Test it ret z ; Ok, got it call incchr ; Increment count xor a dec a ; Set not printable ret ; ; Process one file ; ProcFile: ld hl,(FCNT) ld a,l or h scf ret z ; No more files dec hl ; Update count ld (FCNT),hl ld de,(rdfcb) ; Get FCB ld hl,(FPTR) ; Get search list ld bc,.fdrv+.fname+.fext ldir ; Unpack it ld (FPTR),hl bit _SF,(ix+0) ; Test wild card call nz,Cpname ; Copy name if so call r.open ; Open existing file call w.open ; Open new file ld hl,0 ld (cntint+0),hl ; Clear counter ld (cntint+2),hl ld (cntmsb+0),hl ; Clear counter ld (cntmsb+2),hl ld e,l ; Clear column CNVLOOP: call fgetWS ; Read character inc e dec e ; Test in fist column jr nz,SkipCol0 ; Nope cp '.' ; Test WordStar format command jr z,skpDot ; Yeap, delete it SkipCol0: cp ' ' ; Test control jr c,isCtrl CNVLOOP1: call fput ; Nope, put to file jr CNVLOOP isCtrl: call isValidCtrl ; Test valid control call z,fput ; Yeap, put to file jr CNVLOOP ; ; Found . prefix - skip it ; skpDot: call fgetWSinc ; Read character cp ' ' jr nc,skpDot ; Skip till non printable character skpDot1: call fgetWSinc ; Read character cp ' ' jr c,skpDot1 ; Skip till printable character jr CNVLOOP1 ; ; Get character from WS file ; fgetWSinc: call incchr ; Increment count fgetWS: call fget ; Read character jr c,EOFILE ; End of file push af ; Save character bit 7,a ; Test hi bit set call nz,incmsb ; Increment count pop af and NoMSB ; Strip off hi bit ret ; ; Job done, close file ; EOFILE: pop af ; Clean stack from user call call closef ; Close file jp c,ClsErr ; Error closing file ld de,$FSRC ld hl,(rdfcb) call cpyFN ; Copy name of file ld de,$FDST ld hl,(wrfcb) call cpyFN ; Copy name of file TellFN: ld de,$FRDY call strcn0 ld de,$RDY call strcn0 ; Tell done call isallzero ; Test total zero conversion ld de,$NOCNV jr z,finalstr ; Yeap, tell it call is.d.zero ; Test any deleted push af call z,strcn0 ; Nope, tell it pop af jr z,no.d.del ld de,$WITH call strcn0 ld hl,cntint ; Point to number call prnum ; Give result ld de,X$RDY ; Print message call strcn0 no.d.del: call is.c.zero ; Test changed jr z,nochg call crlf ; Close line ld hl,cntmsb ; Point to number call prnum ; Give result ld de,$CHG ; Print message finalstr: call strcn0 nochg: call crlf ; Close line xor a ; Mark success ret end WSDEL