TTL 'Text formatter' ************************ * * * text formatter V3 * * * ************************ ; ++++++++ Documentation for stand alone +++++++ ; to print a neat copy of a file called: TEXT ; type *PRINT TEXT where PRINT is the name given ; to the object code file produced by assembling ; this source code. ie in general *PRINT ; See ADE user guide for embedded formatter ; commands. ; +++++++++++++++++++++++++++++++++++++++++++++++++ ; the formatter runs as stand alone from disc or ; appended to the editor. Which is stored in condition ALONE ALONE EQU -1 ;Formatter is not part of ADE IF ALONE RAM EQU -1 ;always in RAM OSWRCH EQU $FFEE OSNEWL EQU $FFE7 OSARGS EQU $FFDA OSFIND EQU $FFCE OSBGET EQU $FFD7 OSRDCH EQU $FFE0 OSBYTE EQU &FFF4 OSASCI EQU &FFE3 ORG $2000 FI ; Zero page DSECT IF ALONE DORG EQU &60 ;user zero page ELSE DORG EQU ZPNXT FI ORG DORG VAL1 DS 1 VAL2 DS 1 VAL3 DS 1 WIDTH DS 1 TM DS 1 BM DS 1 PL DS 1 L1 DS 1 NF DS 1 PAGE DS 1 PINC DS 1 LTOC DS 1 LI DS 1 RR DS 1 LM DS 1 ID DS 1 LENA DS 1 LENB DS 1 W1 DS 1 W2 DS 1 IDFLG DS 1 PFLG DS 1 NB DS 1 L2 DS 1 L3 DS 1 SP1 DS 2 SLEN DS 1 NUM DS 1 PFLAG DS 1 ;pause PRINTER DS 1 ;printer suppression used by QV NTEMP DS 1 ;number output flag DEND ; data FCR EQU 13 NPAR EQU 18 ;number of defaults ; buffers ; To enable concurrent use with the editor, DBF ; and STARB are used. DBF is not used by ; the editor in the BBC implentation and STARB is only ; used when processing star commands. ; Each buffer holds a maximum of ; 128 chars, BUFB will overspill into ; the sound workspace if more is typed. IF ~ALONE BUFA EQU $580 BUFB EQU $780 ELSE ;disc start LDA #0 STA PFLAG JSR FMTINT JMP FMTLP FI ******** Initialise formatter *********** FMTINT LDY #0 JSR ETXT ;point start of text / open file LDX #NPAR FMI1 LDA DEFAULT,X STA WIDTH,X DEX BPL FMI1 ; This routine initialises the page ; when any parameters are changed. Initialisation ; exits through here. PAGEIN CLC LDA TM ADC BM CMP PL BCC PI1 ;if error, then restore defaults LDA #8 STA TM LDA #6 STA BM LDA #66 STA PL PI1 SEC LDA PL SBC BM STA L2 ;L2=PL-BM LDA BM LSR CLC ADC L2 SBC #0 ;increment STA L3 ;L3=L2+BM/2-1 FCOX RTS ; output routines FCRLF LDA #10 JSR FCOUT LDA #13 FCOUT BIT PRINTER ;byte sent to printer? BPL FCOZ CMP #13 BEQ FCON ;send CR and printable text to console CMP #32 BCC FCOX FCON JMP OSASCI FCOZ PHA LDA #1 JSR OSWRCH PLA JMP OSWRCH ; Parameter defaults DEFAULT DFB 60,8,6,66,0,128,1,1,0,0,0,10,0,0,0,0,60,0,0 ; Main routine. ; collect one line in BUFA then call the formatter ; Repeat this until end of file. FMTLP LDY #$FF STY VAL1 ; index to BUFA FMT1 INC VAL1 LDY #0 JSR STKPTR ;get one byte, carry set if EOF BCS FMTDONE LDY VAL1 STA BUFA,Y CMP #FCR BNE FMT1 LDA #0 ;terminate with null STA BUFA,Y STY LENA JSR FORMAT ;add line to BUFB and print if necessary BIT $FF ;escape pressed? BPL FMTLP RTS ; wrapup formatting by printing any remaining ; characters in buffer B. FMTDONE JSR BREAK1 ;print remains JMP EJECT ;force new page & exit ******** main routine ********** ; When a line has been transfered to buffer A this ; routine is called to copy it onto the end of buffer B. If the ; total number of characters exceeds the current line width then some ; of the line must be printed. FORMAT LDA LENA BNE F1 F0 JSR BREAK2 ;null line = break FMTEXT LDA #0 STA LENA RTS F1 LDA BUFA ;command? CMP #129 ;RED is command delimiter BNE F3 JMP COMMAND F3 LDA LTOC ;center this line? BEQ F4 ;no JMP CENTER F4 BIT LI BPL F5 JMP LITTERAL ;.LI flag set F5 JSR TRIMA ;remove start and end blanks LDA LENA BEQ F0 ;this has made it a null string LDA LENB ;else add strings BEQ F6 ; (none to add) LDX LENB ; add here LDA #' ; separate STA BUFB,X INC LENB F6 LDX LENA BEQ F7 ;none to add STX VAL1 LDX #0 LDY LENB F8 LDA BUFA,X STA BUFB,Y INX INY DEC VAL1 BNE F8 STY LENB ;final length F7 LDA LENB CMP WIDTH BNE F9 ;needs adjustment JSR BTOA ;else move to print buffer LDA #0 STA LENB JMP PRBUF ;and print F9 BCC FMTEXT ;not enough to print **** format line (.RJ form) **** ; 1. count blanks LDA #0 STA NB LDA WIDTH STA VAL2 STA VAL3 LDA LENB CMP VAL3 ;too long? BCS F10 STA VAL2 STA VAL3 F10 LDX #0 F12 LDA BUFB,X INX CMP #' BNE F11 INC NB F11 DEC VAL3 BNE F12 LDA NB ;hyphenate if less than 2 blanks CMP #2 BCC HYPHEN LDX VAL2 ;last pos + 1 F13 DEX BEQ HYPHEN ;no blanks at all LDA BUFB,X CMP #' BNE F13 STX VAL1 ;else split here JMP CUT ; hyphenate (not at sylable boundry) HYPHEN LDX WIDTH TXA TAY STX LENA DEX LDA #'- STA BUFA,X F14 DEX LDA BUFB,X STA BUFA,X DEY BNE F14 LDX WIDTH DEX TXA JSR MOVEB ; B=MID$(B,WIDTH) JSR TRIMB ; remove balnks ; now print buffer PRBUF JSR FPRINT JSR CRLF JMP F7 ;continue ; cut line CUT STX LENA STX VAL2 F15 DEX LDA BUFB,X STA BUFA,X DEC VAL2 BNE F15 ;move 1st part to A LDX VAL1 INX TXA JSR MOVEB JSR TRIMB BIT RR ;right ragged? BMI PRBUF ; if not rigth ragged, then format JSR TRIMA PAD LDA #0 STA VAL3 PAD1 LDA LENA CMP WIDTH BEQ PRBUF ;exactly right PAD2 LDX VAL3 LDA BUFA,X CMP #' ;find blank BEQ PAD3 INC VAL3 LDA VAL3 CMP LENA ; got to end BCC PAD2 BCS PAD ; blank found at VAL3 PAD3 LDX LENA TXA TAY F17 DEY LDA BUFA,Y STA BUFA,X ;move right side CPY VAL3 BEQ F16 DEX BNE F17 F16 INC LENA INC VAL3 F18 INC VAL3 LDX VAL3 LDA BUFA,X CMP #' BEQ F18 LDA LENA CMP VAL3 BCC PAD BCS PAD1 ;carry on ; print FPRINT JSR PSTART BIT PFLG BMI PRINT1 JSR TOPSPACE ; do top margin at top of page LDA #$80 STA PFLG PRINT1 LDA LM CLC ADC ID TAX ;do indent/margin BEQ F20 F19 LDA #' JSR FCOUT DEX BNE F19 F20 LDY LENA BEQ F24 LDX #0 F23 LDA BUFA,X JSR FCOUT INX DEY BNE F23 F24 LDA W1 ;reset widths BEQ F25 STA WIDTH LDA #0 STA W1 F25 RTS ; do end of line, but not if ; no printing on this page. CRLF BIT PFLG BPL F25 JSR FCRLF INC L1 LDA L1 CMP L2 BNE F25 ;else new page ; start a new page EJECT BIT PFLG ;any print? BPL F25 ;No, so no page throw LDA L1 CMP L3 BCS F26 JSR FCRLF INC L1 BNE EJECT F26 BIT NF ;add page number? BPL NEWPG LDA W2 ;true width LSR CLC ADC LM TAX DEX DEX DEX F26A LDA #' JSR FCOUT DEX BNE F26A LDA #'- PHA JSR FCOUT LDA #' PHA JSR FCOUT ; print page number LDA PAGE LDX #$FF SEC NO1 INX SBC #100 BCS NO1 ADC #100 TAY TXA STA NTEMP BEQ NO2 ORA #'0 JSR FCOUT NO2 TYA ;tens LDX #$FF SEC NO3 INX SBC #10 BCS NO3 ADC #10 TAY TXA BNE NO40 LDA NTEMP BEQ NO4 LDA #0 ;non leading zero NO40 ORA #'0 JSR FCOUT NO4 TYA ;units ORA #'0 JSR FCOUT PLA JSR FCOUT PLA JSR FCOUT F27 JSR FCRLF INC L1 NEWPG LDA L1 CMP PL BCC F27 ;botom space LDA PAGE CLC ADC PINC STA PAGE LDA #0 STA PFLG ; this makes next line init the topspace RTS ; top of page space TOPSPACE BIT PFLAG ;pause? BPL TS0 LDA #15 LDX #1 JSR OSBYTE JSR OSRDCH ;get key TS0 LDA #0 STA L1 TS1 LDA L1 CMP TM BCS TS2 JSR FCRLF INC L1 BNE TS1 TS2 RTS ******* misc subroutines ********* BTOA LDX LENB STX LENA TXA TAY BA1 DEX LDA BUFB,X STA BUFA,X DEY BNE BA1 RTS ; force print, a so called BREAK BREAK1 LDA #0 BEQ BREAK BREAK2 LDA #$80 BREAK STA VAL3 ;flag LDA LENB BEQ BR1 JSR BTOA JSR FPRINT JSR CRLF LDA #0 STA LENB BR1 BIT VAL3 BPL BR2 BR3 LDA TM CMP L1 BCS BR2 JSR CRLF BR2 RTS ; print page start PSTART PHA BIT PFLG BMI PST1 JSR TOPSPACE LDA #$80 STA PFLG PST1 PLA RTS ************************ * * * formatter commands * * * ************************ CNAME ASC 'FJRRLILMWITMBMPAINCIPGPNCEPLRLSK' BRK JTAB DW CFJ-1,CRR-1,CLI-1,CLM-1 DW CWI-1,CTM-1,CBM-1,CPA-1 DW FCIN-1,CCI-1,CPG-1,CPN-1 DW CCN-1,CPL-1,CRL-1,CSK-1 COMMAND LDX #0 CMD1 LDA BUFA+1 ;1st letter AND #$5F ;upper case CMP CNAME,X BNE NXTC LDA BUFA+2 AND #$5F CMP CNAME+1,X BEQ CFOUND NXTC INX INX LDA CNAME,X ;any more? BNE CMD1 JMP FMTEXT ;ignore line if command not known CFOUND LDA JTAB+1,X PHA LDA JTAB,X PHA ; stack address of command so RTS go does it ; get numeric parameter following command, if any LDX #2 ;point char LDY #0 STY NUM FNI1 INX LDA BUFA,X CMP #' ;skip spaces BEQ FNI1 CMP #'9+1 BCS NIDONE CMP #'0 BCC NIDONE AND #$0F STA VAL2 ;ordinal digit LDA NUM ASL ASL CLC ADC NUM ;*10 ASL ADC VAL2 ;+ digit STA NUM JMP FNI1 NIDONE RTS ;to command ****** FJ ****** CFJ LDA #0 STA LI STA LTOC CF1 STA RR CEXIT JSR BREAK1 JMP FMTEXT ****** RR ******* CRR LDA #0 STA LI STA LTOC LDA #$80 BNE CF1 ****** LI ****** CLI LDA #$80 STA LI LDA #0 STA LTOC BEQ CF1 ****** RL ****** CRL LDA #0 STA LTOC LDA #$80 STA LI BNE CF1 ****** LM ****** CLM LDA NUM STA LM JMP FMTEXT ****** WI ****** CWI LDA NUM CMP #8 ;minium BCC CW1 STA WIDTH STA W2 CW1 JMP CEXIT ;via break ******* TM ******* CTM LDA NUM STA TM CT1 JSR PAGEINIT JMP FMTEXT ******* BM ******** CBM LDA NUM STA BM JMP CT1 ******* PA ********* CPA JSR BREAK1 LDA NUM BNE PARA ;no parameter JSR CRLF JMP FMTEXT PARA JSR PSTART LDX NUM PARA1 LDA #' JSR FCOUT DEX BNE PARA1 LDA WIDTH STA W1 PARA2 SEC SBC NUM STA WIDTH ;temp indent PARA21 JMP FMTEXT ******* IN ******* FCIN JSR BREAK1 LDA NUM STA ID BIT IDFLG ;already indenting? BMI PARA21 LDA #$80 ;No, well we are now! STA IDFLG LDA WIDTH STA W2 JMP PARA2 ******* CI ****** CCI BIT IDFLG BPL PARA21 ;no indent LDA #0 STA IDFLG JSR BREAK1 LDA #0 STA ID LDA W2 STA WIDTH JMP FMTEXT ******* PG ***** CPG LDY #1 LDA NUM ;1 is default BEQ CPG1 TAY CPG1 STY PINC JSR BREAK1 ;clear text on last page JSR EJECT JMP FMTEXT ****** PN ****** CPN LDA NUM BEQ PNOFF STA PAGE ;new numbers LDA #$80 PNOFF STA NF JMP FMTEXT ****** CN ******* CCN JSR BREAK1 LDA NUM BNE FCCN1 LDA #$FF ;.CN0 = MAX FCCN1 STA LTOC JMP FMTEXT ****** PL ****** CPL LDA NUM STA PL JSR PAGEINIT JMP FMTEXT ****** SK ****** CSK JSR BREAK LDA NUM BNE FSKIP LDA #1 ;default FSKIP TAX FSK1 JSR BR3 DEX BNE FSK1 JMP FMTEXT ******************************* ; center line of text CENTER DEC LTOC LDA LENA CMP W2 BCC CEN1 CENEX JSR FPRINT JSR CRLF JMP FMTEXT CEN1 LDA W2 SEC SBC LENA LSR CEN3 BEQ CENEX JSR PSTART TAX CEN2 LDA #' JSR FCOUT DEX BNE CEN2 ;adjust margin BEQ CENEX ; output line litterally LITTERAL BIT RR ;right? BPL CENEX JSR TRIMA LDA WIDTH SEC SBC LENA JMP CEN3 ******** string handling routines ******** MOV TAY ;bytes to move BNE MOV1 RTS MOV1 STY VAL2 LDA SLEN SEC SBC VAL2 STA SLEN LDX SLEN LDA #0 STA VAL1 ;index to start MOV2 LDA (SP1),Y LDY VAL1 STA (SP1),Y INC VAL1 INC VAL2 LDY VAL2 DEX BNE MOV2 RTS MOVEB PHA LDA #BUFB STA SP1 LDA LENB STA SLEN PLA JSR MOV LDA SLEN STA LENB RTS ; String trimmer TRIM LDY SLEN ;length of it TR0 DEY LDA (SP1),Y CMP #' BNE TR1 DEC SLEN BNE TR0 TRET RTS TR1 LDY #0 TR2 LDA (SP1),Y CMP #' BNE TR3 INY BNE TR2 TR3 TYA BNE MOV RTS TTRIMA LDX #BUFA LDA LENA BNE TRIMC RTS TTRIMB LDX #BUFB LDA LENB BEQ TRET TRIMC STA SLEN STX SP1+1 STY SP1 JSR TRIM LDA SLEN RTS TRIMA JSR TTRIMA STA LENA RTS TRIMB JSR TTRIMB STA LENB RTS IF ALONE ; STKPTR gets byte ; ETXT opens file ETXT LDX #$A0 ;Read file name LDA #1 LDY #0 JSR OSARGS DEY ET1 INY LDA ($A0),Y CMP #' BEQ ET1 LDX #0 ET3 STA FNAME,X INY INX CMP #FCR BEQ ET2 LDA ($A0),Y JMP ET3 ET2 LDX #>FNAME LDY #