1000 ON ERROR GOTO 8480
1040 FOR SCREEN=1 TO 12:PRINT:NEXT SCREEN
1080 PRINT "******************************************************":PRINT
1120 PRINT "              A U T O P L O T   v 1 . 6":PRINT
1160 PRINT "Program to plot scaled graphs from X and Y input pairs" 
1200 PRINT "             (c) 1984 Alan T. Chattaway.":PRINT
1240 PRINT "Personal use only.  Commercial sale/rental prohibited."
1280 PRINT "This version plots on CRT,  and optionally on printer." :PRINT
1320 '    Revision 1.0 = Original, limited distribution test version.
1360 '    Revision 1.1 = Made valid for non-monotonic functions.
1400 '    Revision 1.2 = "PRINT USING" statements added, to format scales.
1440 '    Revision 1.3 = For 24-line CRT instead of 66-line printer. 
1480 '    Revision 1.4 = Plots on both CRT and standard ASCII printer.
1520 '    Revision 1.5 = Universal version: CRT only, or CRT & printer.
1560 '    Revision 1.6 = Auto-scales both ends of axes (not just top), 
1600 '                   Error trapping & default titles added.
1640 PRINT "******************************************************":PRINT:PRINT
1680 PRINT "Type in the heading for your graph; do not use commas!"
1720 PRINT "           Press RETURN or ENTER when done.":PRINT
1760 INPUT "",HEADING$:PRINT
1800 IF HEADING$="" THEN HEADING$="Graph produced using AUTOPLOT v1.6"
1840 PRINT "******************************************************":PRINT:PRINT
1880 PRINT "Type titles for the X and Y axes (limit 20 characters)"
1920 PRINT "----------------------/234567890123456789\------------"
1960 INPUT "Heading for X column? ",XTITLE$
2000 INPUT "Heading for Y column? ",YTITLE$
2040 IF XTITLE$="" THEN XTITLE$="X values"
2080 IF YTITLE$="" THEN YTITLE$="Y values"
2120 PRINT "******************************************************":PRINT:PRINT
2160 'Take in data in pairs of X,Y: maximum no. of points is 25 each way.
2200 'Enter false data 999,999 to indicate end of list.
2240 DIM X(25):DIM Y(25):DIM CRTY(25):DIM DOUBLES(25)
2280 DIM CRTDOUBLES(25):DIM XLINE(25):N=1
2320 PRINT "Type in paired data values (positive) like this: `X,Y'"
2360 PRINT "Press `RETURN' or `ENTER' key, after typing each pair.":PRINT
2400 PRINT "When  finished,  enter  `999,999'  to terminate input."
2440 PRINT "(In case of error, type control-C and RUN to restart.)":PRINT
2480 PRINT "To force the use of scales of your choice on both axes" 
2520 PRINT "simply include data points representing the lower left"
2560 PRINT "and  upper right corners of  your desired graph,  then" 
2600 PRINT "ignore them  when drawing the line through the points.":PRINT
2640 PRINT "******************************************************":PRINT
2680 INPUT "",X(N),Y(N)
2720 IF X(N)=999 AND Y(N)=999 THEN N=N-1: GOTO 2800
2760 N=N+1: GOTO 2680
2800 'Do D.L.Shell's fast sort into reverse numerical order by X value.
2840 PRINT:PRINT "Sorting for X ..."
2880 SPANSIZE=N
2920 SPANSIZE=INT(SPANSIZE/2)
2960 IF SPANSIZE=0 THEN GOTO 3440
3000 LOOPSIZE=N-SPANSIZE
3040 STARTPLACE=1
3080 FIRSTCOMPARE=STARTPLACE
3120 SECONDCOMPARE=FIRSTCOMPARE+SPANSIZE
3160 IF X(FIRSTCOMPARE)>=X(SECONDCOMPARE) THEN GOTO 3320
3200 SWAP X(FIRSTCOMPARE),X(SECONDCOMPARE):SWAP Y(FIRSTCOMPARE),Y(SECONDCOMPARE)
3240 FIRSTCOMPARE=FIRSTCOMPARE-SPANSIZE
3280 IF FIRSTCOMPARE>0 THEN GOTO 3120   
3320 STARTPLACE=STARTPLACE+1
3360 IF STARTPLACE>LOOPSIZE THEN GOTO 2920
3400 GOTO 3080
3440 PRINT "Scaling X-axis ...":PRINT
3480 'Store top and end values of X-scale to scale the graph later.
3520 XSCALE=X(1):XSCALEND=X(N)
3560 IF X(1)=X(N) THEN PRINT:GOTO 8560
3600 'Now while they're in X-order, print the data table to the screen.
3640 PRINT SPC(INT((80-LEN(HEADING$))/2));HEADING$:PRINT
3680 GOSUB 4040:PRINT
3720 XGAPBACK=INT((20-LEN(XTITLE$))/2):XGAPFRONT=20-LEN(XTITLE$)-XGAPBACK
3760 YGAPBACK=INT((20-LEN(YTITLE$))/2):YGAPFRONT=20-LEN(YTITLE$)-YGAPBACK
3800 PRINT "                  |";SPC(XGAPFRONT);XTITLE$;SPC(XGAPBACK);"|";SPC(YGAPFRONT);YTITLE$;SPC(YGAPBACK);"|"
3840 GOSUB 4080:PRINT:GOSUB 4040:GOSUB 4080:PRINT
3880 FOR LOOP=1 TO N
3920 PRINT CHR$(&HD);TAB(26);USING "####.##";X(LOOP);
3960 PRINT TAB(47);USING "####.##";Y(LOOP):NEXT LOOP
4000 GOSUB 4080:PRINT:GOSUB 4040:GOTO 4120
4040 PRINT "                  -------------------------------------------":RETURN 
4080 PRINT "                  |                    |                    |";:RETURN
4120 PRINT:PRINT "Would you like this printed on paper? (Y/N) ";
4160 PAPER$=INPUT$(1):IF PAPER$="Y" OR PAPER$="y" THEN GOTO 4240
4200 GOTO 4880
4240 'Print same data table to the printer.
4280 PRINT "Ensure printer is ready, then press any key."
4320 READY$=INPUT$(1)
4360 FOR BLANKLINE=1 TO 6:LPRINT:NEXT BLANKLINE
4400 LPRINT SPC(INT((80-LEN(HEADING$))/2));HEADING$:PRINT
4440 FOR BLANKLINE=1 TO 4:LPRINT:NEXT BLANKLINE
4480 GOSUB 4760:GOSUB 4800:LPRINT
4520 LPRINT "                  |";SPC(XGAPFRONT);XTITLE$;SPC(XGAPBACK);"|";SPC(YGAPFRONT);YTITLE$;SPC(YGAPBACK);"|"
4560 LPRINT:GOSUB 4760:LPRINT
4600 FOR LOOP=1 TO N
4640 GOSUB 4800:LPRINT CHR$(&HD);TAB(26);USING "####.##";X(LOOP);
4680 LPRINT TAB(47);USING "####.##";Y(LOOP):NEXT LOOP
4720 LPRINT:GOSUB 4760:GOTO 4840
4760 LPRINT "                  -------------------------------------------":RETURN
4800 LPRINT "                  |                    |                    |";:RETURN
4840 LPRINT CHR$(&HC)
4880 'Do Shell sort again into reverse numerical order by Y value.
4920 PRINT:PRINT "Sorting for Y ..."
4960 SPANSIZE=N
5000 SPANSIZE=INT(SPANSIZE/2)
5040 IF SPANSIZE=0 THEN GOTO 5520
5080 LOOPSIZE=N-SPANSIZE
5120 STARTPLACE=1
5160 FIRSTCOMPARE=STARTPLACE
5200 SECONDCOMPARE=FIRSTCOMPARE+SPANSIZE
5240 IF Y(FIRSTCOMPARE)>=Y(SECONDCOMPARE) THEN GOTO 5400
5280 SWAP Y(FIRSTCOMPARE),Y(SECONDCOMPARE):SWAP X(FIRSTCOMPARE),X(SECONDCOMPARE)
5320 FIRSTCOMPARE=FIRSTCOMPARE-SPANSIZE
5360 IF FIRSTCOMPARE>0 THEN GOTO 5200   
5400 STARTPLACE=STARTPLACE+1
5440 IF STARTPLACE>LOOPSIZE THEN GOTO 5000
5480 GOTO 5160
5520 PRINT "Scaling Y-axis ...":PRINT
5560 'Store top and end values of Y-scale to scale the graph later.
5600 YSCALE=Y(1):YSCALEND=Y(N)
5640 IF Y(1)=Y(N) THEN PRINT:GOTO 8560
5680 'Now while they're in Y-order get ready to print the graph.
5720 'Scale points to fit within 50 horizontal and vertical spaces.
5760 'Also scale another Y-axis for the CRT display (20 lines high)
5800 XFACTOR=(XSCALE-XSCALEND)/50:YFACTOR=(YSCALE-YSCALEND)/50:CRTYFACTOR=(YSCALE-YSCALEND)/20
5840 FOR POINT=1 TO N
5880 X(POINT)=INT((X(POINT)-XSCALEND)/XFACTOR+.5)
5920 CRTY(POINT)=INT((Y(POINT)-YSCALEND)/CRTYFACTOR+.5)
5960 Y(POINT)=INT((Y(POINT)-YSCALEND)/YFACTOR+.5)
6000 'Mark duplicated readings for later action.
6040 FOR LOOP = N TO 2 STEP -1
6080 IF X(LOOP)=X(LOOP-1) AND Y(LOOP)=Y(LOOP-1) THEN DOUBLES(LOOP)=1
6120 IF X(LOOP)=X(LOOP-1) AND CRTY(LOOP)=CRTY(LOOP-1) THEN CRTDOUBLES(LOOP)=1
6160 NEXT LOOP
6200 NEXT POINT
6240 'Now print the graph, starting at the top
6280 GOSUB 7080 'subroutine prints graph on CRT first
6320 PRINT:PRINT "Would you like this printed on paper? (Y/N) ";
6360 PAPER$=INPUT$(1):IF PAPER$="Y" OR PAPER$="y" THEN GOTO 6400 ELSE GOTO 8760
6400 'Print same graph to the printer.
6440 PRINT "Ensure printer is ready, then press any key."
6480 READY$=INPUT$(1)
6520 LPRINT SPC(INT((80-LEN(HEADING$))/2));HEADING$
6560 LPRINT TAB(13-(INT(LEN(YTITLE$)/2)));YTITLE$
6600 FOR HEIGHT=55 TO 5 STEP -1
6640 LPRINT USING "        ####.##  |";(YSCALEND+YFACTOR*(HEIGHT-5));
6680 FOR POINT=N TO 1 STEP -1
6720 IF DOUBLES(POINT)=1 THEN GOTO 6800
6760 IF Y(POINT)=(HEIGHT-5) THEN LPRINT TAB(X(POINT)+19);"*";CHR$(&HD);
6800 NEXT POINT:LPRINT:NEXT HEIGHT
6840 LPRINT "                 -.---------.---------.---------.---------.---------.--"
6880 LPRINT "                  |         |         |         |";SPC(22-LEN(XTITLE$));XTITLE$
6920 FOR LOOP=68 TO 18 STEP -10
6960 XAXIS=(XSCALEND+((XSCALE-XSCALEND)*(LOOP-18))/50)
7000 LPRINT TAB(LOOP-3);USING "####.##";XAXIS;
7040 LPRINT CHR$(&HD);:NEXT LOOP:LPRINT CHR$(&HC);:GOTO 8760
7080 'Subroutine to print graph on CRT before it goes on paper
7120 PRINT SPC(INT((80-LEN(HEADING$))/2));HEADING$
7160 PRINT TAB(13-(INT(LEN(YTITLE$)/2)));YTITLE$
7200 FOR HEIGHT=21 TO 1 STEP -1
7240 COUNT=0:FOR POINT=N TO 1 STEP -1
7280 IF DOUBLES(POINT)=1 THEN GOTO 7360
7320 IF CRTY(POINT)=(HEIGHT-1) THEN GOSUB 7680
7360 NEXT POINT:IF COUNT<>0 THEN GOSUB 7760
7400 PRINT USING "        ####.##  |";(+YSCALEND+CRTYFACTOR*(HEIGHT-1)):NEXT HEIGHT
7440 PRINT "                 -.---------.---------.---------.---------.---------."
7480 'Note: no room for XTITLE$ on CRT printout; used on paper copy only.
7520 FOR LOOP=68 TO 18 STEP -10
7560 XAXIS=(XSCALEND+((XSCALE-XSCALEND)*(LOOP-18))/50)
7600 PRINT TAB(LOOP-3);USING "####.##";XAXIS;
7640 PRINT CHR$(&HD);:NEXT LOOP:RETURN
7680 'Subroutine to collect X-positions of points that are on the same line.
7720 COUNT=COUNT+1:XLINE(COUNT)=(X(POINT)+19):RETURN
7760 'Subroutine to sort X-positions into order and print them.
7800 SPANSIZE=COUNT
7840 SPANSIZE=INT(SPANSIZE/2)
7880 IF SPANSIZE=0 THEN GOTO 8360
7920 LOOPSIZE=COUNT-SPANSIZE
7960 STARTPLACE=1
8000 FIRSTCOMPARE=STARTPLACE
8040 SECONDCOMPARE=FIRSTCOMPARE+SPANSIZE
8080 IF XLINE(FIRSTCOMPARE)>=XLINE(SECONDCOMPARE) THEN GOTO 8240
8120 SWAP XLINE(FIRSTCOMPARE),XLINE(SECONDCOMPARE)
8160 FIRSTCOMPARE=FIRSTCOMPARE-SPANSIZE
8200 IF FIRSTCOMPARE>0 THEN GOTO 8040   
8240 STARTPLACE=STARTPLACE+1
8280 IF STARTPLACE>LOOPSIZE THEN GOTO 7840
8320 GOTO 8000
8360 FOR PLACE=1 TO COUNT
8400 PRINT TAB(XLINE(PLACE));"*";CHR$(&HD);
8440 NEXT PLACE:RETURN
8480 PRINT "******************************************************":PRINT
8520 PRINT "    There has been an error in program execution.":GOTO 8720
8560 PRINT "******************************************************":PRINT
8600 PRINT "******                 WARNING !                ******"
8640 PRINT "******  Largest X (or Y) value = Smallest value ******"
8680 PRINT "There is no range of values so no graph can be plotted" 
8720 PRINT "******   Would you like to run AUTOPLOT again?  ******":GOTO 8880
8760 'End of program; offer another run, then sign off gracefully.
8800 PRINT "******************************************************":PRINT
8840 PRINT "Graph completed. Would you like to run AUTOPLOT again?"
8880 REPLY$=INPUT$(1):IF REPLY$="Y" OR REPLY$="y" THEN RUN
8920 FOR SCROLL=1 TO 10:PRINT:NEXT SCROLL
8960 PRINT "******************************************************":PRINT
9000 PRINT "          Thank you for using AUTOPLOT v1.6":PRINT
9040 PRINT "******************************************************"
9080 FOR SCROLL=1 TO 8:PRINT:NEXT SCROLL:END
1.6":PRINT
9040 PRINT "******************************************************"
9080 FOR SCROLL=1 TO 8:PRIN