title FORMGEN generate form definition file ; ; ; equates for assembly ; INCLUDE RSOPT.INC ; entry cfaddr,cfccp,cfcol,cfcpo,cfddt entry cffdb,cflen,cfline,checkf,cmpde,copyhl entry curdma,defdma,dnline,dskset,dspctl,eosdsk entry fatal,fdbreg,fldovf,fmake,fopen entry getans,hlpmod,imdos,ixpret,kopen entry memout,memtst,nchar,nfield entry pchar,pfield,pstatl,ptform entry recorl,recorp,sdcol,sdline entry srcline,sthlps,tbline,upline,wrnchg ; USER ext wid ;screen width ext ithelp ;initial help level ; IOPACK ext initio ;init the i/o package ext clears ;clear screeen ext inputc ;input a character ext printc ;print a character ext msgrsp ;display message, get response ext wtline ;force line display ext nmscnl ;number of screen lines to display ext clrline ;clear some lines ext dsplay ;display a message ext mycur ;cursor position ext waitif ;wait for I/O, # ms in ACC IF KANJI ext chk2nd ;routine to check if HL points to 2nd byte of Kanji ext knjchr ;Location holding Kanji input character (2 bytes) ext knjflg ;Flag to indicate Kanji was input and it's in KNJCHR. ext knjout ;routine to output KANJI to printer (or CRT) ext knjtst ;Test sets CY flag if byte in A is in Kanji Range ENDIF ; TIF ext tof ;top of form ext dspcur ;display cursor ext dspfld ;redisplay line ext dspline ;mark line for display ext chkdot ;set Z if need to skip dot line ext skpdot ;skip dot line ext scrlif ;scroll screen if nessecary ext newscn ;display screen ext newhlp ;re-display help lines ext help ;toggle help display ext error,error1 ;display error ext hlevel ;set help block ; FORMRE ext abort ;abort with error ext startm ;print signon ext gtform ;get form name ext rdform ;read the form ext mkform ;make new form image ext nwform ;new form flag (new form if nz) ext fcols ;number of columns in form ext flines ;number of lines in form ext plines ;number of printing lines in form ext fimage ;form image start ext fields ;field descriptions ext ldbs ;line defintion blocks ext stkptr ;stack pointer top ext freest ;free space start ext nxfree ;next free memory ext ckfree ;check number free bytes left ext wtform ;write form back to disk ext chain ;chain next program ext stachr,staacc ;store byte in form ext stackp ;set stack pointer ext prvfdb ;point previous fdb ext nxtfdb ;point next fdb ext fndfld ;convert fdb number to pointer ext fndblk ;convert any number to pointer ext resdsk ;restore current disk for exit ext curdsk ;current disk ext setdsk ;set current disk drive ext initms ;init messages ext ptitem ;point item ext lenedw ;length of edit word ext filedk ;disk drive for form name ext upper ;convert to upper case ext copyright ;long copyright notice ; FDB ext fdbdel ;adjust fdb for charcter deletion ext fdbins ;adjust fdb for character insertion ext splitf ;adjust fdb for field split by non-field character ext joinif ;adjust fdb for putting control character next to field ext fdbafc ;adjust fdb for added field character ext fdbcbl ;adjust fdb for toggling control break ext fdbdlf ;adjust fdb for removing field ext cpyrfs ;adjust references for line copy ext fdbcnt ;number of FDB's in line copy ext addldb,remldb ;add, remove ldb ext cpyfdb ;copy fdb for line buffer moves ext cpyldb ;copy ldb for line buffer moves ext adjlin ;adjust fdb for adding, removing line ext pntcol ;point column ext pntlen ;point length ext pntfdb ;point current fdb ext pntldb ;point current ldb ext move ;copy up or down ext fstart ;get column of FDB start ext tstfld,tsthl ;set Z, C flags according to current byte only ext tstprv,tstnxt ;set Z if previous, next byte is field ext tstacc ; " ext chksub ;set Z if subflg or sbfflg ext chkfld,chkhl ;set Z if current byte is part of a field ext chkfb ;set Z, C for urrent byte setting CY only if not trmflg ext cbsides ;set Z if field on either side ext chkcb ;set nz if in control break field ext subde ;HL-DE -> BC ; DEFLD ext defld ;define field ext defline ;define line ext defile ;define file ext defcnd ;define conditions ext deflde ;clean up after defld call for error ext resfrm ;restore form for error message ext erchar ;set character into message for error ext meslen ;length for cnvasc ext cnvasc ;convert binary to ascii ; ENDCHK ext endchk ;check form for exit ext prform ;list form ; REMSG ext hlpbk1,hlpbk2 ;help blocks ext hlpbk3,print ext hlpbkr,hlpbkc ext hlpbkf,hlpbkl ext hlpbkx ext fdfmsg,cdfmsg ext clrlen,clearm ext screen ;screen number in status line ext exit1 ext emsg3,emsg5 ext emsg6,emsg7 ext emsg9,emsg10 ext emsg11,emsg12 ext nfmsg,xerrm4 ext spltms,delbms ext erms4,cl0lst ext ldbchr,sumchr ext stline,stcol ext stfldd,stflds ext stfldl,stnum ext stlen,stpos ext stedc ext indptr,ctlmsg ext shortl,modptr ; ; equates ; ctlc equ 3 ctle equ 5 ctlf equ 6 ctli equ 09 ctlj equ 0AH ctlk equ 0BH ctll equ 0CH ctlm equ 0DH ctlo equ 0FH ctlp equ 10H ctlr equ 12H ctls equ 13H ctlu equ 15H ctlx equ 18H ctly equ 19H ctlz equ 1AH cr equ 0DH underl equ 5FH IF HILITE remvid equ 7fh ;true for HIGHLIGHTING ENDIF IF ATEBIT remvid equ 0FFH ;true for 8 BIT CHAR SET ENDIF rubout equ 7FH fldflg equ 0 unuflg equ 1BH trmflg equ 1CH cblflg equ 1DH subflg equ 1EH sbfflg equ 1FH fdedw1 equ 81H ;item number of 1st mask frn equ 32 ;FCB offset to record number boot equ 0 bdos equ 5 selecf equ 14 openf equ 15 creatf equ 22 renamf equ 23 setdma equ 26 tbline equ 120H defbuf equ 80H page 60 ; come from ddt ; cfddt: lhld bdos+1 dcr h sphl xra a sta defbuf ;no command line ; ; come from ccp ; cfccp: xra a sta chainf ;clear/set chain flag call stackp ;set stack point & read message file call initio ;init i/o package shld freest ;free space start call startm ;put up the signon jmp form2 ; ; come from external program ; ixpret: ori 80H sta chainf ;clear/set chain flag mov a,c call setdsk ;restore logged disk call stackp ;set stack point & read message file call initio ;init i/o package shld freest ;free space start ; form2: call initms ;init messages lda chainf ora a cz copyright ;display copyright unless we chained form3: call gtform ;get the form name call rdform ;read it if there cnz mkform ;make it if it's not there call clears ;clear screen again call tof ;position at top of form call initus ;init form parameters, tab stops and help block lda chainf add a cz defile ;define files unless coming from rgen and want layout form5: call pstatl ;print status line call phelp ;print help block call dspcur ;position cursor lda chainf ani 7FH cpi ctlc cnz inputc ;get a character call form7 ;do something with it form5a: call scrlif ;scroll form if nessecary xra a sta chainf jmp form5 ;redisplay it ; ; do something with the input character ; form7: lxi h,wrncnt mvi m,1 ;init warning count mov c,a call erchar ;put character into error message lda cfcol ora a mov a,c cz ckchar ;if column zero, check for legal jc badchr ;illegal character cpi rubout jz rubchr ;jif special control cpi underl jz setfld ;set field character cpi ' ' jnc putchr ;jif not control character lxi h,formt ;dispatch table ; ; dispatch routine ; mvi b,0 dad b dad b mov e,m inx h mov d,m push d ret ; ; check for column zero character legal ; ckchar: call upper ;convert to upper case mov c,a lxi h,sumchr ;ok if summary character cmp m rz lxi h,cl0lst ;list of legal characters ckchr2: inr m dcr m stc ;set CY for bad character rm ;not in list cmp m rz ;good inx h jmp ckchr2 ; ; dispatch table for form generation ; formt: dw notimp ; dw pfield ;^A previous field dw addcol ;^B add a column dw exit ;^C chain next program dw nchar ;^D next character dw upline ;^E cursor up line dw nfield ;^F next field dw dchar ;^G delete next character dw pchar ;^H cursor previous character dw tab ;^I cursor next tab dw toghlp ;^J toggle help dw setcb ;^K set control break dw restore ;^L restore screen dw nxline ;^M next line dw addline ;^N add line dw togctl ;^O toggle display control characters dw cpyline ;^P copy line to line buffer dw setfld ;^Q set field character dw editf ;^R edit field dw pchar ;^S previous character dw delcol ;^T delete column dw settab ;^U toggle tab stop dw insert ;^V insert next character dw prform ;^W list form dw dnline ;^X down line dw deline ;^Y delete line dw delfld ;^Z delete field dw notimp ;^[ dw notimp ;^\ dw notimp ;^] dw notimp ;^^ dw pretab ;^_ back tab ; ; restore screen display ; restor: call clears ;clear screen call newscn ;restore ret page ;************************************************ ; ; CURSOR MOVEMENT ROUTINES ; ;************************************************ ; ; ^D = bump current position, adjusting cfaddr, cfline, cfcol, sdcol, sdline ; nchar: call ldregs call nchar1 ;do the position increment IF KANJI mov a,c ;For Kanji, check if we landed on 2nd byte, which is call chk2nd ; illegal. (CHK2ND returns CY=1 if 2nd byte) cc nchar1 ; Bump position to next byte if we did hit 2nd byte. ENDIF ; ; store registers for cursor move ; stregs: shld cfaddr xchg shld sdcol mov h,b mov l,c shld cfcol ret ; ; load registers for cursor move ; ldregs: lhld cfcol mov b,h mov c,l lhld sdcol xchg lhld cfaddr ret page ; ; bump current position in registers ; BC = cfcol/cfline ; DE = sdcol/sdline ; HL = cfaddr ; nchar1: call nchar0 ;bump position jm nchar3 ;jif next line lda dspctl ora a ;set zero if we are not displaying ^ characters cz tsthl ;set cy if control character jc nchar1 ;jif to skip ^ character ret ; ; bump position ; nchar0: call tsthl ;get form byte and test inx h ;form address rm ;rif next line inr e ;assume printing character cc nchar2 ;process non-printing character inr c ;bump form column xra a ;clear M, C ret ; ; add 1 to col in E if dspctl is on, else subtract 1 ; nchar2: lda dspctl ; 0 / 0FFH cma ; 0FFH / 0 add a ; 0FEH / 0 inr a ; 0FFH / 1 add e mov e,a ret ; ; bump line ; nchar3: inr b ;bump form line mvi c,0 inr d ;bump display line mvi e,0 nchar4: call skpdot ;skip dot control lines cpi 0FFH ;check for end form rnz call begreg jmp nchar4 ; begreg: lhld fimage lxi d,0 mov b,d mov c,e ret page ; ; ^S, ^H = go to previous character position ; pchar: call ldregs call pchar1 IF KANJI mov a,c ; Check if cursor positioned on 2nd byte of KANJI call chk2nd ; If so, move back one position cc pchar1 ; (CHK2ND takes offset fm start of line in A reg) ENDIF call stregs ret ; ; adjust printing col in E for control character ; pchar0: lda dspctl ora a jnz pchar2 ;two characters print if displaying control characters pop psw ;don't return ; ; decrement current position in registers ; BC = cfcol/cfline ; DE = sdcol/sdline ; HL = cfaddr ; pchar1: dcx h ;form address call pchar6 ;get byte and test jz pchar3 ;jif previous line dcr c ;bump form column call tstacc ;set cy if non-printing cc pchar0 ;process non-printing character pchar2: dcr e ;assume printing character ret ; ; previous line ; pchar3: call pline1 ;skip to start of current line pchar4: mov a,m cpi cr rz call nchar1 ;skip to end of current line jmp pchar4 ; ; search backwards from current line to first previous printing line ; pline: dcx h pline1: call pchar7 ;test for cr jnz pline inx h ;point line start call pline2 ;skip to start of previous line call chkdot ;set Z to skip dot command line jz pline ;use pline to replace 0FFH with endregs if wraps mvi e,0 mov c,e ret ; ; skip to start of previous line ; pline2: call chkdot dcx h jz pline3 ;don't change printing line because it was a skip-line dcr d pline3: dcx h ;skip back to cr/0FFH of previous line call pchar6 ;test for end line jnz pline3 inx h ;point start of line dcr b ;we crossed a line boundary ret ; pchar6: mov a,m cpi 0FFH rz cpi cr ret ; ; load current byte and return Z set if CR ; pchar7: mov a,m cpi cr rz cpi 0FFH rnz call endreg dcx h ret page ; ; RETURN = cursor beginning of next line ; nxline: call ldregs ;HL=col/line, DE=printing col/line, BC=form address call nxlin1 ;move to start of next line lda cfcol ora a cnz nchar1 ;column 1 unless we were in col zero call stregs ret ; ; adjust registers to start of next line ; nxlin1: call nplin1 ;skip to next line call nchar3 ;adjust other pointers ret ; ; ^X = cursor down a line ; dnline: call ldregs mov a,e ;printing column push psw call nxlin1 ;move to start of next line dnlin1: pop psw call dnlin2 IF KANJI mov a,c ; Check if cursor on 2nd byte of KANJI (C=col#) call chk2nd ; If so reposition cursor to 1 before cc pchar1 ; current location. ENDIF call stregs ret ; dnlin2: cmp e rz ;done if at position in psw rc ;or past it call ptcol1 ;bump column preservng ACC jp dnlin2 ;jif more ret ;or at cr ; ; ^E = cursor up a line ; upline: call ldregs mov a,e ;printing column push psw call pline ;move to start of of previous line jmp dnlin1 ;adjust column page ; ; ^F = next word or next field ; nfield: call chkfld ;set Z in field jnz nword ;if not in field, go to next word call nfld2 ;set registers nfld0: call nxtfdb ;point to next fdb jnz nfld1 ;jif not end mov h,d mov l,e ;set HL = ldbs/fields inx h ;point first field nfld1: call fdbreg ;get FDB regs jz nfld0 ;not on a printing line ret ; ; set HL = fdb/ldb pointer ; DE = fields/ldbs ; nfld2: lda cfcol ora a jz nfld3 ;jif for ldbs lhld fields xchg call pntfdb ret ; nfld3: lhld ldbs xchg call pntldb ret ; ; get and set registers for FDB in HL ; returns Z flag set if on a non-printing line ; fdbreg: push h ;save FDB pointer in case not printing push d call pntcol ;point to column mov e,m ;get column inx h mov d,m ;get line xchg call ptform ;get form address and printing position call fdbrg1 cnz stregs ;set registers unless not on printing line pop d pop h fdbrg1: lda dspctl ora a rnz ;all lines are printing lda lnflag cpi '.' ret page ; ; next word ; nword: call ldregs call ckwrd1 ;set Z if between words nwrd1: cnz nwrd3 jnz nwrd1 ;locate word end nwrd2: call nwrd3 jz nwrd2 ;find next word call stregs ret ; ; skip to next character and set flag ; nwrd3: call nchar1 ; ; set NZ if byte in HL belongs to a word ; ckword: call loopck ;check loop jz setwrd ;return with word flag set if looped ckwrd1: mov a,c ora a rz ;treat col 0 as space mov a,m cpi cr rz ;treat CR like space ani remvid cpi ' ' rz call chkhl ;set Z if part of a field ret ; setwrd: ora h ;set nz ret page ; ; ^A = previous word or previous field ; pfield: call chkfld ;set Z if in a field jnz pword ;if not in field find previous word call nfld2 ;point to fdb/ldb & fields/ldbs pfld0: call prvfdb jnz pfld1 mov h,d mov l,e mov a,m dcr a ;field number of last field call fndblk ;get last fdb ptr pfld1: call fdbreg ;get and set registers jz pfld0 ;line wasn't printing ret ; ; previous word ; pword: call ldregs call pwrd3 ;previous characacter pwrd1: cz pwrd3 jz pwrd1 ;locate word pwrd2: call pchar1 ;because we don't want wrap around to flag a word call ckwrd1 jnz pwrd2 ;find space preceeding call nchar1 call stregs ret ; pwrd3: call pchar1 ;previous character jmp ckword ;return z set if in a word page ; ; ^I = move cursor to next tab stop ; tab: call cktline ;check tab line jz tab3 ;jif no more stops on this line tab1: mov a,m cpi cr cz ichar0 call nchar1 ;next positon tab2: call chktab ;set z if at tab or wrapped jnz tab1 ;loop if not done IF KANJI mov a,c ; For Kanji, check if TAB lands on 2nd byte of Kanji. call chk2nd ; If we are on 2nd byte (CHK2ND returns CY=1), then cc nchar1 ; reposition cursor to next forward byte location. ENDIF call stregs ret ; ; no more stops on this line ; tab3: call nxline ;move to start of next line call cktline ;check for tab stops on this line jnz tab2 ;jif found one ret ;there aren't any tab stops ; ; set Z if no more tab stops on line ; cktlin: call ldregs push h call pnttab cktln1: inx h mov a,m cpi cr jz cktln2 ;jif no more tab stops on the line cpi '.' jnz cktln1 ora a cktln2: pop h ret ; ; ^- = move cursor to previous tab stop ; pretab: call ldregs ptab1: call pchar1 ;next positon call chktab ;set z if at tab or wrapped jnz ptab1 ;loop if not done IF KANJI mov a,c ; For Kanji, check if TAB lands on 2nd byte of Kanji. call chk2nd ; If we are on 2nd byte (CHK2ND returns CY=1), then cc pchar1 ; reposition cursor to previous byte location. ENDIF call stregs ret ; ; ^U = set/clear a tab stop ; settab: call ldregs call pnttab ;point to current position in tab line mvi b,' ' cmp b jnz settb1 ;jif tab is set mvi b,'.' settb1: mov m,b ;set/clear the tab call newhlp ;re-display ret ; ; set Z if at a tab or wrapped ; chktab: push h call pnttab pop h cpi '.' rz loopck: lda cfcol cmp c rnz ;no wrap lda cfline cmp b ret ; ; point to current position in tab line ; pnttab: lxi h,tbline ;point tab line push d mvi d,0 dad d pop d mov a,m ret ; ; ^O = toggle control character display ; togctl: call togdsp ;do the toggle ora a lda flines cz gpline ;get printing lines if control line display went off ora a jz togdsp ;can't toggle if no printing lines sta plines lhld cfcol ; ; recalculate position for form chanage ; newpos: push h ;save current position call initpos ;set initial position pop h call ptprnt ;location position now call stregs call newscn ret ; ; toggle dspctl ; togdsp: lxi h,dspctl mov a,m cma mov m,a ;do the toggle ret ; ; return number of printing lines in ACC ; gpline: lhld fimage mvi d,0 gplin1: call npline ;skip to next printing line mov a,m cpi 0FFH jnz gplin1 mov a,d ret ; ; skip to next line, keeping count of printing lines in D ; npline: call chkdot jz nplin1 inr d ; ; skip to next line ; nplin1: mov a,m inx h cpi cr jnz nplin1 ;skip to start of next line ret ; ; get form address and printing position ; ; HL = requested line, col ; ; returns: ; HL = form address ; DE = printing line, col ; BC = form line, col ; ptform: mov a,l push psw ;request col mov a,h push psw ;request line call gtregs ;get register values of closest known point pop psw call ptline ;point line start in ACC mov a,m sta lnflag ;set first byte of current line pop psw call ptcol ;point column in ACC ret ; ; point line start in ACC ; ptlin2: call pline2 ;skip to start of previous line ptlin4: pop psw ;target line number ptline: cmp b rz ;rif at line in ACC push psw jc ptlin2 ;go backwards call npline ;skip to start of next line, bumping D if printing inr b jmp ptlin4 ; ; point col in ACC ; ptcol: cmp c rz ;rif at target col call ptcol1 ;bump col preserving ACC jp ptcol ret ; ; bump col preserving ACC ; ptcol1: push psw call tsthl ;set M if at cr cp nchar0 ;bump position, setting M if at cr xthl ;get target col into H mov a,h pop h ret ; ; get closest registers to line in H ; gtregs: lda cfline mov e,a ;save ora a ;clear cy rar ;divide by 2 inr a cmp h jnc begreg ;current line <= cfline/2, start at fimage lda flines cmp h jz endregs add e rar inr a cmp h jc endregs ;current line <= (fline+cfline)/2, start at cfline call ldregs ;get registers from cfaddr mvi e,0 inr c gtreg1: dcr c ;skip to line start rz dcx h jmp gtreg1 ; ; load end of form registers ; endreg: lhld ldbs dcx h lda flines mov b,a lda plines mov d,a xra a mov c,a mov e,a ret ; ; set registers (as ptform) to next printing position ; ptprnt: call ptform lda dspctl ora a rnz ;all print lda lnflag dcr d ;assume line non-printing cpi '.' jz nxlin1 ;good assumption inr d ;restore line number call tsthl ;set CY if non-printing cc nchar1 ;move to next printing character ret page ;************************************************ ; ; CHARACTER DELETION/INSERTION ROUTINES ; ;************************************************ ; ; RUB = delete the previous character ; rubchr: call pchar lda cfcol ora a jz pchar ;don't delete in col 0 call chkcr rz inx h mov a,m cpi cr jz dchar call dspcur mvi c,' ' call putchr call pchar ret ; ; ^G = delete the character under the cursor ; IF KANJI dchar0: call chkcr ; This entry used when only 1 byte to be deleted, rz ; EVEN WHEN IT MAY BE A KANJI. call dchar3 jmp dchar1 ENDIF dchar: call chkcr rz ;can't delete line end IF KANJI ; This is the Normal entry point. Handles Kanji well. call dchar3 jmp dchar2 dchar3: ENDIF call fdbdel ;adjust fdb for deleting character lxi d,0FFFFH ;number of bytes to move lhld cfaddr IF KANJI ret dchar2: mov a,m ;Get byte from form we are about to wipe out call knjtst ;Check if 1st byte of Kanji jnc dchar1 ;Jif not Kanji -- no special gears needed push h ;save current address in form inx h ;where to move from call move ;overwrite 1st byte of Kanji push d ;save move count call fdbdel ;adjust FDB's for removing 2nd byte of Kanji pop d ;restore move count pop h ;restore current form address dchar1: ENDIF inx h ;first byte to move call move ;do the move call dspfld call cblif ;extend if control break field ret ; ; insert space at cursor ; ichar0: call stregs ;for tab call call ldregs ;stregs messes them up ichar: push h push d push b lhld cfcol ;first, check for line too long mvi l,0 call ptform ;(E=0) ora a ;clear cy ichar1: jnc ichar2 ;jif 1 character inr e ichar2: inr e call tsthl ;set cy if two-character, minus if cr inx h jp ichar1 ;jif not cr mov a,e dcr a cpi 254 jnc ichar3 IF KANJI lda insknj ;Do we want to check if inputting kanji? ora a jz ichar4 ;Jif not check for Kanji input mov a,e dcr a cpi 253 ;For Kanji col 252 is the max col number jnc ichar3 ;If over max then print error message ichar4: ENDIF call fdbins lxi d,1 lhld cfaddr call move mvi c,' ' call stachr call dspfld ori 0FFH ;say successful pop b pop d pop h ret ; ichar3: lxi h,emsg7 call error xra a ;say we didn't pop b pop d pop h ret ; chkcr: lhld cfaddr mov a,m cpi cr ret page ; ; ^V = insert next character into form ; insert: call ichar ;make space rz ;line too long mvi a,0FFH call waitif lxi h,print mvi c,0 call error1 ;print menu, get character mov c,a cpi underl jz setfld ;jif field byte cpi rubout jz dchar ;get rid of it lxi h,badlst ;bad character list call ckchr2 ;set Z if in bad list jz inserr ;jif illegal character call tstacc ;set CY if control character cc joinif ;if control character, combine if field on either side lhld cfaddr call stachr ;put control character IF KANJI call knjtst ;If inputting Kanji characters... jnc insrt2 ; push b ;...don't forget to insert 2nd byte also. (save 1st 1) call ldregs ;load registers for current byte in form call nchar1 ;advance pointers to next byte call stregs ;store updated pointers pop b ; (restore 1st byte Kanji into C) call ichar ;Try inserting space for our 2nd byte jz insrt1 ;If failed to insert, delete 1st byte from form lda knjchr ;Else get 2nd byte from KNJCHR stax d ;...and store it in the form jmp insrt2 insrt1: call pchar ; Comes here if deleting 1st byte Kanji from form lhld cfaddr ; Backup 1 byte, then store a space into that loc mvi m,' ' ; And let DCHAR erase it (Space put so DCHAR won't call dchar ; detect KANJI and erase 2 bytes) ret insrt2: ENDIF call dspfld ;display call nchar ret ; inserr: call erchar ;put character into error message badchr: lxi h,erms4 call error ret ; ; bad character list ; must be in order ; badlst: db ctli,ctlj,ctlk,ctll,ctlm db ctlo,ctlp,ctlu,ctlz db 1BH,1DH,1EH,1FH db 0FFH ; ; put character in C register into form ; putchr: IF KANJI ; 4 possible cases arise for KANJI version input: ; 1. Kanji overwriting ANK ; 2. ANK overwriting Kanji ; 3. Kanji overwriting Kanji ; 4. ANK overwriting ANK (previously existing code) ; lda knjflg ;Was 2-byte Kanji input? ora a lhld cfaddr ; (get current byte in form into A) mov a,m ; (in preparation for calling KNJTST jz putch3 ;Jif not -- a single ANK byte it was ; ; Kanji overwriting Something.. ; call knjtst ;Are we overwriting Kanji? jnc putch1 ;No -- overwriting ANK ; ; Kanji overwriting Kanji.. ; call stachr ;Ok, update 1st byte of kanji into form inx h ;Increment pointer into form lda knjchr ;Get 2nd byte of Kanji input call staacc ;update 2nd byte of Kanji into form image call dspfld ;mark line for display jmp nchar ;Finally update cursor position to 1 character right ; ; Kanji overwriting ANK ; putch1: lda knjflg sta insknj ; Set flag to tell ICHAR that we want Kanji check EOL call ichar ; Insert extra space for Kanji, then mvi a,0 sta insknj ; Reset flag. rz ; Rif line is too long. call stachr ; Put the 1st byte of Kanji into form call ldregs ; Then update pointers to point to next byte call nchar0 ; We can't call PUTCH4 nor NCHAR cuz it checks for call stregs ; 2nd byte of Kanji and bumps cursor twice. putch2: lda knjchr ; Now insert the 2nd byte, which was just mov c,a ; fetched from KNJCHR and put in C. jmp putch4 ; ; ANK overwriting Something.. ; putch3: call knjtst ; What are we overwriting? jnc putch4 ; Not Kanji, so must be ANK over ANK. Skip down. ; ; ANK overwriting Kanji. ; mvi m,' ' ; Put space into form so that DCHAR will only delete push b ; 1 of the 2 Kanji bytes. (save input char in C) call dchar ; Delete one extra character that Kanji took up. pop b ; and fall into PUTCH4 (restore input char) ; ; ANK overwriting ANK. ; putch4: ENDIF call chkcr cz ichar ;insert space if at CR rz ;line too long lda cfcol ;follows chkcr to set HL to cfaddr ora a jz putctl ;jif control character call chkfld ;set Z if in a field push b cz splitf ;if it's a field, it will be split pop b lhld cfaddr call stachr ;put down new background call dspfld ;display character call nchar ret ; ; put CTL character, HL = cfaddr ; putctl: lda ldbchr cmp c jz ptctl1 ;jif putting down ldb character cmp m cz remldb ;remove ldb if was there call stachr ;put down charcter call chkdot ;check for making line into . command line cz togctl ;toggle display if it makes the line non-printing call dspfld ;display character call dnline ;next line ret ; ptctl1: cmp m cnz addldb ;add ldb if not already there call stachr ;put down character call defline ;enter user definition call newscn call dnline ret page ;************************************************ ; ; PRINT STATUS LINE ; ;************************************************ pstatl: push h push d push b lhld modptr xchg push d lxi h,clearm lxi b,clrlen mov b,c call pstat6 pop d lxi h,filedk mov a,m inx h call pstatd ;put disk drive if present stax d ;put space/: inx d mvi b,8 call copyhl ;move file name to status line lda hlpmod cpi 'F'-'0' jz pstat7 ;jif file definition cpi 'X'-'0' jz pstatw mvi a,3 sta meslen ;set message length call chkfld ;set Z if in field mov c,m ;save field flag jnz pstats ;short status line if not in field call pntfdb ;point fdb push h inr a ;bump field number lxi d,stnum call pstat4 ;NUM= call pntlen lxi d,stlen call pstat4 ;LEN= mov a,c call chksub ;set Z if subflg or sbfflg lda cfcpo mov c,a jz pstat0 ;use cfcpo for cursor position if doing defld lhld cfaddr mvi c,0FEH pstatx: inr c pstaty: call chkfb dcx h jz pstatx jc pstaty mov a,c pstat0: inr a ;position lxi d,stpos call pstat4 ;POS= pop h call lenedw ;get length of edit word into acc ora a lxi d,0 jz pstat1 ;jif no edit word mov e,a ;save length edit word call ptitem db fdedw1 mov b,d dad b ;add offset within field mov a,m ;get it dad d ;point content control mov d,m mov e,a pstat1: lxi h,stedc call indptr mov m,e ;set edit characters inx h mov m,d call tstfld ;set Z if at actual field character lxi h,stflds ;field status start lda stfldl ;assume at field character jz pstat2 lda shortl ;at control character pstat2: call pstat3 ;copy NUM= LEN= and possibly POS= EDC= pstats: lhld cfcol ;line and column mov a,h inr a lxi d,stline call pstat4 ;LIN= lda cfcpo add l lxi d,stcol call pstat5 ;COL= lda cflen sta meslen ;restore meslen for defld pstat9: lxi b,0CE00H ;don't add base, 78 bytes, line 0 lhld modptr call dsplin ;mark line for display pop b pop d pop h ret ; ; copy number of characters in ACC from address in HL to status line ; pstat3: mov b,a lxi d,stfldd jmp pstat6 ;convert addresses and do the move ; pstat4: xchg call indptr ;convert indirect pointer to address xchg jmp cnvasc ; pstat5: jnz pstat4 ;jif not col 000 lxi h,ctlmsg mvi b,3 pstat6: call indptr ;convert to message pointer xchg call indptr xchg call copyhl ;clear or copy field status ret ; ; put file definition message into status line ; pstat7: lxi h,fdfmsg pstatv: call indptr pstat8: mov a,m ora a jz pstat9 ;done, go write stax d inx h inx d jmp pstat8 ; ; put condition message into status line ; pstatw: lxi h,cdfmsg jmp pstatv ; ; put disk drive into status message ; pstatd: ora a jz pstate adi 'A'-1 stax d inx d mvi a,':' ret ; pstate: mvi a,' ' stax d inx d ret page ; ; ^Q = set field character ; setfld: call tstfld ;set Z if at a field character jz stfld2 ;done if already a field character call chkcr ;set Z if at a CR cz ichar ;insert a space if at line end rz ;line too long IF KANJI call knjtst ;If overwriting a Kanji, then jnc stfld3 ; delete the one extra space that Kanji call dchar ; takes up by first deleting the whole kanji call ichar ; and then reinserting a space for the field char stfld3: ENDIF call fdbafc ;adjust fdb for added field character lhld cfaddr call cbsides ;get field character jz stfld1 mvi a,fldflg ;this is field creation stfld1: call staacc ;put field byte call dspfld ;display the line call cblif ;extend if control break field stfld2: call nchar ;reposition cursor ret ; ; extend if control break field ; cblif: call chkcb ;check if control break field mvi c,cblflg ;control break flag cnz fllfld ;fill entire field with flag if control break ret ; ; ^K = toggle control break/not control break field status ; setcb: call chkfld jnz setcb1 ;jif not a field push psw ;save field byte call fdbcbl ;adjust fdb's pop psw xri cblflg ;toggle control break flag mov c,a ; ; make entire field a control break field ; includes redisplaying the field ; fllfld: push b call fstart ;get field start pointer into HL pop b fllit1: call chkfb jc fllit2 ;control character jnz dspfld ;field end call stachr fllit2: inx h jmp fllit1 ;field character ; ; ^Z = delete field ; delfld: call chkfld jnz setcb1 ;jif wasn't a field byte call fdbdlf ;remove fdb mvi c,' ' call fllfld ;fill field with ' ' ret ; ; ^R = define field ; editf: call chkfld jnz setcb1 ;jif not in field call defld ;change field definition call newscn ;redisplay screen ret ; setcb1: lxi h,emsg3 jmp nogood page ; ; ^N = add a line from the line buffer ; not permitted if number of lines = 255 ; addlin: call endregs ;position at form end call pchar1 ;end of last printing line mov c,b ;source line number lda cfline addln1: mov b,a ;destination line number call mvline ;move the line call newscn ret ; ; ^P = move current line into the line buffer ; not permitted if number of lines = 255 ; cpylin: lda cfline mov c,a ;source line number lda flines jmp addln1 ; ; ^Y = delete line unless form empty ; deline: lxi h,emsg6 lda plines dcr a jz error lda cfline call sncols ;set ncols, HL = start of next line cma inr a mov e,a mvi d,0FFH ;DE = number of bytes to move call move ;do the move lda cfline mov d,a mvi e,0FFH call adjlin ;adjust FDB's for removing the line lxi h,plines dcr m lxi h,flines dcr m ;one less line mov a,m lhld cfcol cmp h jnz delin1 dcr h ;deleting last lien fo form delin1: call newpos ;re-calc position ret ; ; subroutine to move a line ; C = source line number ; B = destination line number ; mvline: lxi h,emsg5 lda flines inr a jz error ;jif already 255 lines mov a,c cmp b jc mvl1 inr a ;source line will get bumped when add destination mvl1: sta srcline ;save source line number push b mov a,c ;use original because destiantion hasn't been added yet call sncols ;set number of columns in source line pop b lhld cfcol push h ;save current position mov h,b mvi l,0 push h ;save current position at destination start call ptform ;HL = destination line start lda ncols mov e,a mvi d,0 push h call move ;make room at destination mvlin0: mvi m,' ' ;clear in case run out of memory inx h dcr e jnz mvlin0 dcx h mvi m,cr lxi h,plines inr m ;bump printing line count lxi h,flines inr m ;bump line count mov d,b ;destination line number mvi e,1 call adjline ;adjust line numbers in FDB's call initpos ;set initial position lda srcline mov h,a mvi l,0 call ptform ;HL = source line pointer mvi c,0 ;flag, if C=1, don't copy fdb again, it's already done lda ncols mov b,a xchg ;put source in DE, dest in HL pop h xthl ;save destination line start in form shld cfcol ;set to start of destination line pop h xra a sta fdbcnt ;clear number of fdb's ldax d cpi '*' ;ldb flag lda srcline cz cpyldb ;copy ldb if needed mvlin1: ldax d xchg call chkhl xchg jnz mvlin2 ;jif not in a field shld cfaddr ;set destination address dcr c ;if C = 1, cpyfdb has already been called mvi c,2 lda srcline ;source line number cnz cpyfdb ;make copy of FDB mvlin2: dcr c ;this sets C=0 if this is a field terminator ldax d mov m,a ;move line byte inx h inx d push h lxi h,cfcol inr m pop h dcr b jnz mvlin1 pop h call newpos ;recalc position call cpyrfs ;adjust references ret ; ; set number of columns in line in ACC ; sncols: mov h,a mvi l,0 call ptform ; mvi e,0 sncol1: mov a,m inr e inx h cpi cr jnz sncol1 mov a,e sta ncols ret page ; ; ^B = add a column ; addcol: lxi h,addcl1 ;routine to set Z if splitting a field call doform ;set Z if condition occurred lxi h,spltms cz getans ;ask if sure, set Z if no lxi h,addcl2 cnz doform call newscn ret ; ; set Z if splitting a field ; addcl1: call tstprv ;set Z if previous string contains field character rnz call chkfb ;set Z if current character is field byte or CY if ctl cc tstnxt ret ; ; insert a character and return NZ ; addcl2: call ichar ori 0FFH ;clear Z ret ; ; add/remove/test column in form ; HL says which ; doform: shld dofrm1+1 lhld sdcol push h ;save current position dofrm1: call ichar ;insert/delete character jz dofrm3 ;abandon if Z flag set dofrm2: IF KANJI call ldregs ;Here we wish to delete 1 physical column regardless call nchar1 ; of being on a Kanji or not. Therefore this detour call stregs ; to NCHAR1 is taken so won't check for KANJI ELSE call nchar ;next character ENDIF lhld sdcol pop d push d ;starting position mov a,e cmp l jnz dofrm2 ;search for same column position mov a,d cmp h jnz dofrm1 ;jif at same col position in another line ori 0FFH ;say we finished dofrm3: pop h ret ; ; ^T = delete column ; delcol: lxi h,tstfld call doform ;set Z if condition occurred lxi h,delbms cz getans ;ask if sure, set Z if no lxi h,dlcol1 cnz doform call newscn ret ; dlcol1: IF KANJI call dchar0 ;use routine that doesn't check for Kanji in this case. ELSE call dchar ENDIF ori 0FFH ret page ; ; get answer from operator ; HL = pointer to: ; message, al, default, answer list, 0 ; ; return answer number in ACC ; getans: push h ;save message start push b mvi b,1 mvi a,5 call clrline ;clear space for message mvi c,0 ;line = 1, column = 0 call dsplay ;display message mov c,m ;get default push h lhld mycur call printc ;display default shld mycur ;restore cursor call inputc ;get responce into ACC cpi ' ' mov c,a cnc printc ;echo response unless non-printing pop h ;restore pointer to default mov a,c call cnvans ;convert answer to code in ACC pop b ;restore entry registers pop h jc getans ;try again if bad input push psw call newhlp pop psw ret ; ; check answer against list and convert to code ; HL = list pointer ; ACC = answer -> code ; ; returns CY set if bad answer ; cnvans: mov c,m ;get default mvi b,0FFH ;get code here call upper ;convert to upper case cpi cr jz cnvan1 ;jif to use default in C mov c,a cnvan1: inr b inx h mov a,m ora a stc rz ;quit if end list (bad input) cmp c jnz cnvan1 ;jif not yet matched mov a,b ora a ret page ; ; ^C = done with form ; exit: call endchk ;perform check for exit cpi ' ' rz ;space = continue cpi ctlx jz defcnd ;define conditions cpi ctlf jz defile ;define files push psw ;save end flag dcr a cz exit0 ;^A, see if ok to abort push psw cnz wtline ;wait for form to restore (unless abort) pop psw cnz wtform ;write form to disk unless ^A (abort) call resdsk ;restore current disk for exit pop psw cpi ctls ;^S = exit jz exit3 cpi ctlc rz ;^C = continue after form save lxi h,exit1 ;file name jnc chain ;^D = chain next program exit3: lhld stkptr ;^S and ^A come here sphl call clears ;clear screen again xra a sta defbuf ;clear command line jmp form3 ;exit with ^A, ^X ; exit0: lxi h,xerrm4 mov c,a ;clear c call error1 call upper ;convert to upper case ani 3FH ;convert to control character cpi ctly rz ;yes abort pop h ;don't return to exit pop psw ret ; ; check free space for amount in BC ; checkf: call memtst ;set CY if enough rc memout: lxi h,emsg9 ;out of memory message check1: call error lhld stkptr ;abort cammand sphl call resfrm ;restore form if in defld call deflde ;clean up after defld call newscn jmp form5a ; ; set CY if enough memory left ; memtst: push h push d lhld nxfree dad b xchg lhld bdos+1 call cmpde pop d pop h ret ; ; crash ; fatal: lxi d,emsg10 jmp abort ; ; too many fields ; fldovf: lxi h,emsg12 jmp check1 ; ; not implemented yet ; notimp: lxi h,erms4 nogood: call error ora a ret ; ; give warning for edit/range word change ; wrnchg: push h lxi h,wrncnt dcr m lxi h,emsg11 cz error ;first time only pop h ret page ; ; init for program start ; initus: lxi h,tbline ;set tab stops mvi b,0 init1: mvi m,' ' init2: inx h inr b jz init3 mov a,b cpi 80 jnc init1 ;no initial tab stops after col 72 ani 7 jnz init1 mvi m,'.' jmp init2 init3: mvi m,cr mvi a,0FFH sta dspctl ;start with control characters displayed call initpos ;set initial position call nchar ;don't start out in control column lda chainf add a jnz init4 ;jif not doing defile sta nmscnl ;don't display form if going into defile call pstatl ;print status line for re-entry init4: lda nwform ora a mvi a,3 ;assume not first time jz init5 ;jif not first time inr a init5: lxi h,ithelp ;initial help level cmp m jc init6 ;ok if maximum is higher mov a,m mvi m,3 init6: call sthlps ;display help block in ACC ret ; ; set initial position ; initpo: call begregs call stregs ret ; ; display full page help ; sthlp4: mvi c,0 ;line 0 lhld modptr call dspline ;display help screen number change lxi b,100H+ctlj ;only accept control J lxi h,nfmsg call msgrsp ;if first time display help message call toghlp lxi h,nwform mov a,m mvi m,0 ora a cz newscn ;redisplay screen unless start up ret ; ; toggle help block ; toghlp: lda hlpmod ;help mode dcr a jnz sthlps lda ithelp ;get from user patch area sthlps: lxi h,hlpmod ;entry with new mode in ACC mov b,m ;get old mov m,a ;set new dcr a cz help ;toggle out if now it is 1 dcr b cz help ;toggle help back in if was out (old mode was 1) ; ; display current help block ; phelp: lda hlpmod adi '0' cpi '4' cc phelp1 ;switch to C menu (in col 0) if 1, 2 or 3 lxi h,screen call indptr cmp m rz mov m,a cpi '4' jz sthlp4 ;menu 4 is different lxi h,phelp3 phelp2: cmp m inx h mov e,m inx h mov d,m inx h jnz phelp2 xchg call hlevel ;mark help block for display ret ; ; switch to C menu in col 0 ; phelp1: cpi '0' rc ;but not if help screen '*' lxi h,cfcol inr m dcr m rnz mvi a,'C' ret ; phelp3: db '*' dw hlpbkl db '1' dw hlpbk1 db '2' dw hlpbk2 db '3' dw hlpbk3 db 'C' dw hlpbkc db 'F' dw hlpbkf db 'R' dw hlpbkr db 'X' dw hlpbkx ; cmpde: mov a,d cmp h rnz mov a,e cmp l ret ; copyhl: mov a,m stax d inx h inx d dcr b jnz copyhl kopen: ret ; ; do open and create in a reasonable way ; fopen: mvi c,openf jmp fstuff fmake: mvi c,creatf fstuff: call imdos ;do it cpi 245 jnc bad ;jif error push h lxi h,frn dad d ;point next record xra a ;set z for success mov m,a ;clear next record pop h ret bad: ora a ret ; ; imdos simulator ; imdos: push h push b push d mov a,c cpi setdma cz imdos2 ;save current dma address sui openf cpi renamf-openf+1 jnc imdos1 ldax d mov b,a ;save the disk call dskset ;select disk push b call bdos ;do the function pop b pop h ;fcb mov m,b ;restore disk xchg ;put fcb in DE ora a ;test result pop b pop h ret imdos1: IF KANJI mvi a,5 ; Is function 'output to printer'? cmp c jnz imdos3 mov c,e ; KNJOUT needs char in C register call KNJOUT ; routine to handle KANJI output to PRINTER mvi c,5 ; Restore function number in C imdos3: ENDIF call bdos ora a pop d pop b pop h ret ; imdos2: xchg shld curdma ;save current dma address for keystroke capture xchg ret ; ; select disk (and clear byte in FCB) ; dskset: push h push d ;save fcb push b ;and function ldax d dcr a ;make into CP/M disk jp dskst1 lda curdsk dskst1: sta eosdsk ;in case error mov e,a mvi c,selecf call bdos ;select disk pop b pop d pop h xra a stax d ;clear disk ret ; defdma: push h push b push d mvi c,setdma lxi d,defbuf jmp imdos1 curdma: dw 80H ;save current dma for keystroke capture recorp: ds 2 recorl: ds 2 cfcpo: db 0 cfaddr: ds 2 ;pointer into form ; ; next 22 bytes must be in this order ; its an FDB for upflds ; cffdb: dw 22 ;number of bytes cflen: db 1 ;field length cfcol: db 0 ;column in form image cfline: db 0 ;line in form image db 0 ;field type db 0 ;edit flags db 0 ;pad character db 0 ;input file number db 0 ;input field number db 0 ;input index field if reference db 0 ;output file number db 0 ;output field number db 0 ;output index field if reference db 0 ;control break level db 0 ;equivalent field db 0 ;calculation/input prompt expression length db 0 ;UNLESS/THEN expression count db 0 ;print expression length db 0 ;output expression length db 0 ;clear if expression db 0 ;field name hlpmod: db 4 ;start with help block 4 wrncnt: ds 1 ;warning message count srclin: ds 1 ;source line number for mvline chainf: ds 1 ;chain flag, 0=no chain, ^C = exit eosdsk: ds 1 ;disk in error dspctl: db 0FFH ;nz to display control characters sdcol: db 0 ;number of printing characters to current column sdline: db 0 ;number of printing lines to current line ncols: ds 1 ;number of bytes in line lnflag: ds 1 ;first byte in line IF KANJI insknj: db 0 ;Flag to tell ICHAR to check for EOL for KANJI ;Set and reset in routine PUTCHR ENDIF end