10 REM RUNOFF - A simple text formatter February, 1982 20 REM 30 REM COPYRIGHT 1982 John M. Nevison Associates, Concord, Mass. 32 REM 34 REM Timothy J. Stein 36 REM John M. Nevison Associates 38 REM Concord, Mass. 01742 40 REM (617) 369 4214 42 REM 44 REM Takes a text file and formats it for output to a line 46 REM printer, screen, or another file. All lines starting with 48 REM a period are considered formatting commands. The program 50 REM recognizes these commands: 52 REM .PAGE or .P Force a new page 54 REM .SPACING n or .S n Set line spacing to n 56 REM .LEFTMARGIN n or .LM n Set left margin to column n 58 REM .RIGHTMARGIN n or .RM n Set right margin to column n 60 REM .JUSTIFY or .J Fill lines to fit 62 REM .NOJUSTIFY or .NJ Don't bother 64 REM .CENTER or .C Center all lines 66 REM .NOCENTER or .NC Don't center any more 68 REM .INCLUDE file or 70 REM .I file Read text from file specified 72 REM 73 REM A few notes: 74 REM 1. The program does not reassemble lines. If a line is longer 75 REM than the distance from LM to RM it will be truncated. 76 REM It will also not be justified or centered. 77 REM 2. The INCLUDE command cannot be nested. That is, an INCLUDED 78 REM file cannot contain an INCLUDE command. 79 REM 80 REM MAJOR VARIABLES: 81 REM L$ The current line 82 REM PAGE$ One page of lines 83 REM V.xxx Values used globally 84 REM S.xxx Switches used globally 85 REM 87 'PAGE 90 '------------------------------------------------------------------------ 91 ' MAIN LOOP 92 ' 93 ' 1. Set up initial values, get command names 94 ' 2. Get file names 95 ' 3. IF input file entered THEN 96 ' UNTIL eof seen on input file 97 ' 1. Get a page of text 98 ' 2. Send it out 99 ' 4. Close files and exit 100 '----------------------------------------------------------------------- 102 ' 105 GOSUB 500 'Initialize 110 GOSUB 2000 'Get file names 120 IF INFILE$ = "" THEN 200 130 GOSUB 5000 'Assemble a page 140 GOSUB 11000 'Print it out 150 IF S.EOF = 0 THEN 130 'Until EOF 160 CLOSE 200 ' 210 SYSTEM 390 'PAGE 400 '------------------------------------------------------------------------ 500 'SUB: Initialize 510 '------------------------------------------------------------------------ 515 ' 520 DIM PAGE$(60) 'page of text 530 S.JUSTIFY = 0 'justify off 540 S.CENTER = 0 'center off 550 S.EOF = 0 'not eof yet 560 S.PAGE = 0 'not end of page yet 565 V.PAGE = 1 'page number 567 V.INF = 1 'current input file number 570 V.LM = 10 'left margin value 580 V.RM = 70 'right margin value 585 V.COL = V.RM - V.LM + 1 'current column width 590 V.SPACING = 1 'single spacing value 595 V.CC$ = "." 'command character 597 V.PAGESIZE = 50 'page length 600 ' 605 DATA 9 606 'number of commands (DIM if greater than 10) 610 DATA PAGE, P 620 DATA SPACING, S 630 DATA LEFTMARGIN, LM 640 DATA RIGHTMARGIN, RM 650 DATA JUSTIFY,J 660 DATA NOJUSTIFY, NJ 670 DATA CENTER, C 680 DATA NOCENTER, NC 685 DATA INCLUDE, I 690 ' 700 READ NCMDS 710 FOR I = 1 TO NCMDS 720 READ CMD$(I), CMDA$(I) 730 NEXT I 740 ' 750 RETURN 1900 'PAGE 1910 '----------------------------------------------------------------------- 1920 ' SUB: Get file names 1921 ' IN: none 1922 ' OUT: infile$ - input file name (null if none typed) 1930 '---------------------------------------------------------------------- 1990 ' 2000 CLS 2100 LOCATE 10,26 2110 INPUT "File: "; INFILE$ 2120 IF INFILE$ = "" THEN 2410 'return 2130 ON ERROR GOTO 2160 2140 OPEN INFILE$ FOR INPUT AS #1 2150 GOTO 2220 2160 LOCATE 11,26 2170 IF ERR = 53 THEN 2200 2180 PRINT "File open error ";ERR 2190 GOTO 2210 2200 PRINT "No such file" 2210 RESUME 2100 2220 ' 2225 V.INF = 1 2230 LOCATE 11,26 2240 INPUT "Output device: ";O$ 2250 ON ERROR GOTO 2280 2260 OPEN O$ FOR OUTPUT AS #2 2270 GOTO 2310 2280 LOCATE 12,26 2290 PRINT "Illegal device, error ";ERR 2300 RESUME 2230 2310 ' 2311 IF LEFT$(O$,3) <> "LPT" AND LEFT$(O$,3) <> "lpt" THEN 2318 2312 A$=CHR$(27)+"D" 2313 LPRINT A$; 2314 FOR I = 8 TO 64 STEP 8 2315 LPRINT CHR$(I); 2316 NEXT I 2317 PRINT #2,CHR$(0); 2318 ' 2319 ON ERROR GOTO 0 2320 LOCATE 12,26 2330 PRINT " " 2410 RETURN 4900 'PAGE 4910 '----------------------------------------------------------------------- 5000 'SUB: Assemble a page 5001 ' IN: v.inf - input file number 5002 ' OUT: s.eof - if end of input file seen 5003 ' s.page - if .page command seen 5004 ' v.inf - changed if .include command seen 5005 ' linecount - number of lines this page 5006 ' page() - assembled page 5007 '----------------------------------------------------------------------- 5010 ' 5020 LINECOUNT = 0 5030 GOSUB 5500 'Get a good line 5040 IF S.EOF = 1 OR S.PAGE = 1 THEN 5100 5045 IF S.GOODLINE = 0 THEN 5070 5050 GOSUB 6000 'Insert a line in the page 5060 IF LINECOUNT >= V.PAGESIZE THEN 5100 5070 GOTO 5030 5100 ' 5110 RETURN 5400 'PAGE 5410 '----------------------------------------------------------------------- 5500 'SUB: Get a good line 5501 ' IN: v.inf - input file number 5502 ' OUT: l$ - line 5503 ' s.goodline - 0 if no text line, 1 if so 5504 ' v.inf - may have changed if .include seen 5505 ' s.eof - may be set if end of file seen 5507 ' NOTE: also processes commands seen; if .justify or .center are 5508 ' in effect, l$ is returned as justified or centered. 5509 '----------------------------------------------------------------------- 5510 ' 5515 S.GOODLINE = 0 5520 IF EOF(V.INF) THEN 5585 5530 LINE INPUT #V.INF,L$ 5540 LLEN = LEN(L$) 5550 IF LEFT$(L$,1) <> V.CC$ THEN 5560 5553 GOSUB 6500 'Do command 5555 GOTO 5600 5560 IF S.JUSTIFY = 1 THEN GOSUB 8000 'Justify 5570 IF S.CENTER = 1 THEN GOSUB 8500 'Center line 5575 S.GOODLINE = 1 5580 GOTO 5600 5585 ' 5587 IF V.INF = 1 THEN 5595 5589 CLOSE V.INF 5591 V.INF = 1 5593 GOTO 5520 5595 ' 5597 S.EOF = 1 5600 ' 5610 RETURN 5900 'PAGE 5910 '----------------------------------------------------------------------- 6000 'SUB: Insert a line 6001 ' IN: l$ - line to be inserted 6002 ' linecount - current number of lines this page 6003 ' OUT: page$() - page array 6004 ' linecount - modified to reflect line plus spacing 6005 '----------------------------------------------------------------------- 6010 ' 6020 LINECOUNT = LINECOUNT + 1 6030 PAGE$(LINECOUNT) = LEFT$((SPACE$(V.LM-1) + L$),V.RM) 6040 IF V.SPACING <= 1 THEN 6100 6050 FOR I = 1 TO V.SPACING - 1 6060 LINECOUNT = LINECOUNT + 1 6070 PAGE$(LINECOUNT) = " " 6080 NEXT I 6100 ' 6110 RETURN 6400 'PAGE 6410 '----------------------------------------------------------------------- 6500 'SUB: Do command 6501 ' IN: l$ - line with command on it (first char is ".") 6502 ' OUT: none 6503 ' NOTE: as side effect, the command is done 6504 '----------------------------------------------------------------------- 6510 ' 6520 TPOS = 2 6530 GOSUB 9000 'Get token 6540 IF TOKEN$ = "" THEN 6610 6550 FOR I = 1 TO NCMDS 6560 IF CMD$(I) = TOKEN$ THEN 6650 6570 NEXT I 6580 FOR I = 1 TO NCMDS 6590 IF CMDA$(I) = TOKEN$ THEN 6650 6600 NEXT I 6610 ERRX$ = "Illegal command <" + TOKEN$ + ">" 6620 GOSUB 10000 'Print error 6630 GOTO 6690 6650 ' 6660 ON I GOSUB 6700, 6800, 6900, 7000, 7100, 7200, 7300, 7400, 7500 6670 ' 6690 RETURN 6695 'PAGE 6697 '----------------------------------------------------------------------- 6700 'SUB: page eject 6701 '----------------------------------------------------------------------- 6710 ' 6720 S.PAGE = 1 6730 RETURN 6740 ' 6790 '----------------------------------------------------------------------- 6800 'SUB: spacing 6801 '----------------------------------------------------------------------- 6810 ' 6820 GOSUB 9300 'Get value 6830 IF VALUE = -.001 THEN VALUE = 1 6840 V.SPACING = VALUE 6850 RETURN 6860 ' 6890 '----------------------------------------------------------------------- 6900 'SUB: left margin 6901 '----------------------------------------------------------------------- 6910 ' 6920 GOSUB 9300 6930 IF VALUE = -.001 THEN VALUE = 1 6940 IF V.RM > VALUE THEN 6947 6942 ERROR$ = "Left margin greater than right margin" 6944 GOSUB 10000 6946 GOTO 6950 6947 V.LM = VALUE 6948 V.COL = V.RM - V.LM + 1 6950 RETURN 6960 ' 6990 '----------------------------------------------------------------------- 7000 'SUB: right margin 7001 '----------------------------------------------------------------------- 7010 ' 7020 GOSUB 9300 7030 IF VALUE = -.001 THEN VALUE = 1 7040 IF V.LM < VALUE THEN 7047 7042 ERROR$ = "Left margin greater than right margin" 7044 GOSUB 10000 7046 GOTO 7050 7047 V.RM = VALUE 7048 V.COL = V.RM - V.LM + 1 7050 RETURN 7060 ' 7090 '----------------------------------------------------------------------- 7100 'SUB: justify 7101 '----------------------------------------------------------------------- 7110 ' 7120 S.JUSTIFY = 1 7130 RETURN 7140 ' 7190 '----------------------------------------------------------------------- 7200 'SUB: nojustify 7201 '----------------------------------------------------------------------- 7210 ' 7220 S.JUSTIFY = 0 7230 RETURN 7240 ' 7290 '----------------------------------------------------------------------- 7300 'SUB: center 7301 '----------------------------------------------------------------------- 7310 ' 7320 S.CENTER = 1 7330 RETURN 7340 ' 7390 '----------------------------------------------------------------------- 7400 'SUB: nocenter 7401 '----------------------------------------------------------------------- 7410 ' 7420 S.CENTER = 0 7430 RETURN 7440 'PAGE 7490 '----------------------------------------------------------------------- 7500 'SUB: include 7501 '----------------------------------------------------------------------- 7510 ' 7512 IF V.INF = 1 THEN 7520 7514 ERRX$ = "Cannot nest .include files" 7516 GOSUB 10000 7518 GOTO 7650 7520 GOSUB 9000 'Get token 7530 ON ERROR GOTO 7560 7540 OPEN TOKEN$ FOR INPUT AS #3 7550 GOTO 7600 7560 ON ERROR GOTO 0 7570 ERRX$ = "Error opening .include file " + TOKEN$ 7580 GOSUB 10000 7590 GOTO 7650 7600 ' 7610 V.INF = 3 7620 ' 7650 RETURN 7900 'PAGE 7910 '----------------------------------------------------------------------- 8000 'SUB: JUSTIFY 8001 ' IN: l$ - line to justify 8002 ' v.col - column width 8003 ' OUT: l$ - line justified 8004 '----------------------------------------------------------------------- 8010 ' 8020 SCOUNT = 0 8030 FOR I = 1 TO LLEN 8040 IF MID$(L$,I,1) = " " THEN SCOUNT = SCOUNT + 1 8050 NEXT I 8060 IF SCOUNT = 0 THEN 8400 8070 LET SLOP = V.COL - LLEN 8080 IF SLOP <= 0 THEN 8400 8090 LET SSIZE = INT(SLOP/SCOUNT) 8100 LET SREM = SLOP - SSIZE * SCOUNT 8110 L2$ = L$ 8120 L$ = "" 8130 FOR I = 1 TO LLEN 8140 X$ = MID$(L2$,I,1) 8150 L$ = L$ + X$ 8160 IF X$ = " " THEN 8190 8180 GOTO 8300 8190 'else 8200 FOR J = 1 TO SSIZE 8210 L$ = L$ + " " 8230 NEXT J 8240 IF SREM <= 0 THEN 8300 8250 L$ = L$ + " " 8260 SREM = SREM - 1 8300 NEXT I 8310 LLEN = LEN(L$) 8320 ' 8400 RETURN 8490 'PAGE 8495 '----------------------------------------------------------------------- 8500 'SUB: Center 8501 ' IN: l$ - line to center 8502 ' v.col - column width 8503 ' OUT: l$ - line center 8504 '----------------------------------------------------------------------- 8510 ' 8520 SLOP = V.COL - LLEN 8530 IF SLOP <= 0 THEN 8700 8540 L$ = SPACE$(SLOP/2) + L$ 8550 LLEN = LEN(L$) 8560 ' 8700 RETURN 8900 'PAGE 8910 '----------------------------------------------------------------------- 9000 'SUB: Get token 9001 ' IN: l$ - line in which to look for token 9002 ' tpos - character to start the search 9003 ' llen - length of line 9004 ' OUT: token$ - token found, or null if none 9005 ' tpos - moved to point to char after token 9007 ' NOTE: tokens delimited by spaces, leading spaces ignored, all 9008 ' alpha characters shift to upper case 9009 '----------------------------------------------------------------------- 9010 ' 9020 TOKEN$ = "" 9030 FOR I = TPOS TO LLEN 9040 X$ = MID$(L$,I,1) 9050 IF X$ <> " " THEN 9080 9060 NEXT I 9070 GOTO 9250 9080 ' 9090 FPOS = I 9100 FOR I = FPOS TO LLEN 9110 X$ = MID$(L$,I,1) 9120 IF X$ = " " THEN 9140 9130 NEXT I 9140 ' 9150 TPOS = I + 1 9160 TOKEN$ = MID$(L$,FPOS,TPOS-FPOS-1) 9162 X = LEN(TOKEN$) 9164 FOR I = 1 TO X 9165 X$ = MID$(TOKEN$,I,1) 9166 IF X$ < "a" OR X$ > "z" THEN 9169 9167 X$ = CHR$(ASC(X$) - 32) 9168 MID$(TOKEN$,I,1) = X$ 9169 NEXT I 9170 ' 9250 RETURN 9290 'PAGE 9295 '----------------------------------------------------------------------- 9300 'SUB: get value 9301 ' IN: l$ - line to find value on 9302 ' tpos - place to start search 9303 ' OUT: value - numeric value of next token, or -.001 if none 9304 ' tpos - updated to point after token 9305 '----------------------------------------------------------------------- 9310 ' 9320 GOSUB 9000 'Get token 9330 ON ERROR GOTO 9400 9340 VALUE = VAL(TOKEN$) 9350 GOTO 9450 9400 RESUME 9410 9410 VALUE = -.001 9420 ' 9450 ON ERROR GOTO 0 9460 RETURN 9470 ' 9900 'PAGE 9910 '----------------------------------------------------------------------- 10000 'SUB: print errors 10001 '---------------------------------------------------------------------- 10010 ' 10020 PRINT "ERROR: ";ERRX$;" in this line: " 10030 PRINT " ";L$ 10040 RETURN 11000 'SUB: print a page 11001 ' IN: page$() - page array 11002 ' linecount - number of lines assembled for this page 11003 ' v.page - current page number 11004 ' OUT: v.page - next page number 11005 ' s.page - reset to 0 11006 '---------------------------------------------------------------------- 11010 ' 11020 IF LINECOUNT > V.PAGESIZE THEN LINECOUNT = V.PAGESIZE 11030 FOR I = 1 TO LINECOUNT 11040 PRINT #2,PAGE$(I) 11050 NEXT I 11060 FOR I = 1 TO V.PAGESIZE - LINECOUNT + 4 11070 PRINT #2," " 11080 NEXT I 11090 PRINT #2,SPACE$((V.RM - 7)/2);"--";V.PAGE;"--" 11100 V.PAGE = V.PAGE + 1 11110 PRINT #2,CHR$(12) 11120 S.PAGE = 0 11130 RETURN 11140 END 11900 'PAGE 11910 '----------------------------------------------------------------------