1000 DEFINT A-Z 1010 ON ERROR GOTO 3760 1020 COMMON I,J,K,X,Y,T$,R$,S$,T1$,SKIPPARSE,FT,SEARCH, C,N,NC,P6,P7,P8,P9,PI,S,T,T1,T2,C(),B$(),N$(), SEARCHWORD$(),SEARCHFIELD(),SKIPWORD$(),LOOKFIELD(),DD$(),F$,FT$ 1040 NK=0:DIM S(NC,4) 'field #, num?, length, pad? 1050 Y=T2-T1+1 1060 DIM D(Y) 1070 X=INT(LOG(Y)/LOG(2)) 1080 DIM LST(X),HST(X) 'lo and hi stacks 1090 ' ENTER HERE TO RE-SPECIFY 1100 GOSUB 4010 1110 D$(0)="":ERASE D$:DIM D$(T2-T1+1) ' do here for recycle (erased below) 1120 PRINT"SORT -- March 20, 1982 1125 ' by Dan Dugan -- public domain 1130 PRINT:PRINT"Arranges a selected set of records in numerical or alphabetical order. 1140 PRINT"To quit this activity, enter 'x' in response to a 'y/n' question. 1150 IF T1=1 AND T2=N THEN GOTO 1200 1160 PRINT:PRINT"Shall the output include the records outside the range sorted? (n/y) "; 1170 A$=INPUT$(1): IF A$=CHR$(13) THEN A$="n" 1180 PRINT A$: IF A$="y" THEN S9=1 1190 IF A$="x" THEN 3400 1200 PRINT 1210 PRINT"Please define the key fields for sorting in '"F$".' The fields are: 1220 PRINT: GOSUB 4190 ' show 1230 PRINT"The file will be re-arranged according to the contents of the key fields. 1240 PRINT"Enter the primary key field number first, then any others you wish to 1250 PRINT"be sorted within that order, etc. 1260 S6=1:KLEN=0:KLENFLAG=0 ' any alph field will change S6 to 0; key length 1270 PRINT:FOR I=1 TO NC 1280 PRINT I;". ";: INPUT"Enter field number of key field (0 when done) ";S(I,1) 1290 IF S(I,1)=0 THEN 1420 1300 IF S(I,1)<1 OR S(I,1)>NC THEN PRINT"Field"S(I,1)"??? Enter again." GOTO 1280 1310 S(I,2)=0:IF RIGHT$(N$(S(I,1)),1)="n" THEN S(I,2)=1 ELSE S6=0 1320 '(if just one is alpha, do alpha sort) 1330 INPUT"Number of characters in field to use (RETURN for all)";S(I,3) 1332 IF S(I,3) THEN 1334 ELSE 1340 1334 S(I,4)=0:PRINT"Do you want to pad shorter fields to that length? (n/y) "; :A$=INPUT$(1):IF A$=CHR$(13) THEN A$="n" 1335 PRINT A$:IF A$="y" THEN S(I,4)=1 1340 IF S(I,3) THEN 1350 ELSE PRINT"You want to sort on all characters of "; :GOTO 1360 1350 PRINT"You want to sort on the first"S(I,3)"characters of "; 1360 PRINT LEFT$(N$(S(I,1)),4)"? (y/n) ";: A$=INPUT$(1):IF A$=CHR$(13) THEN A$="y" 1370 PRINT A$:IF A$="x" THEN 3400 1380 IF A$<>"y" THEN PRINT"Entry cancelled; ready for key"I"again.":GOTO 1280 1390 IF S(I,3) THEN KLEN=KLEN+S(I,3) ELSE KLEN=KLEN+10:KLENFLAG=1 1400 PRINT 1410 NEXT I 1420 NK=I-1 1430 IF S(1,1)=0 THEN 3400 'quit 1440 PRINT:PRINT"Ascending order? (y/n) "; 1450 A$=INPUT$(1): IF A$=CHR$(13) THEN A$="y" 1460 PRINT A$: IF A$="n" THEN S8=1 1470 IF A$="x" THEN 3400 1480 ' OUTPUT SWITCH (P7) 1490 P7=0 1500 PRINT:PRINT"Shall the product of the sort overlay the original file? (y/n) "; 1510 A$=INPUT$(1): IF A$=CHR$(13) THEN A$="y" 1520 PRINT A$:IF A$="x" THEN 3400 1530 IF A$="n" THEN P7=1:GOTO 1600 1540 IF A$<>"y" THEN 1500 1550 ' YES, OVERLAY 1560 IF (T1=1 AND T2=N) OR S9=1 THEN 1630 1570 PRINT:PRINT"NOT ALLOWED - Overlaying part of file on file will erase records 1580 PRINT"outside of range.": PRINT:GOTO 1480 1590 ' NAME OUTPUT FILE 1600 PRINT:INPUT"Name of sort product file (no prefix or suffix) ";F2$ 1610 IF F2$="" THEN 1480 1620 X$=F2$:GOSUB 3920:F2$=Y$ ' ucv 1630 ' SHOW SORT SET-UP 1640 GOSUB 4010 'cs 1650 PRINT"SETUP FOR SORT 1660 PRINT: IF T1=1 AND T2=N THEN PRINT"Sort all records ("N")": GOTO 1710 1670 PRINT"Sorting range of records from"T1"to"T2" 1680 ON S9+1 GOTO 1690,1700 1690 PRINT"The output will be the range of records only.": GOTO 1710 1700 PRINT"The output will be the entire file with the selected range sorted. 1710 PRINT:PRINT"Records will be put in order by examining": PRINT"the contents of the sort key fields." 1720 PRINT:FOR I=1 TO NK 1730 PRINT TAB(29);:PRINT USING"##";I;: PRINT". "LEFT$(N$(S(I,1)),4); 1740 PRINT TAB(40);:IF S(I,3) THEN PRINT S(I,3) ELSE PRINT" all" 1750 NEXT I 1760 PRINT:IF KLENFLAG THEN 1762 ELSE 1766 1762 PRINT"ESTIMATED string space needed for the key array is"KLEN*(T2-T1+1): GOTO 1768 1766 PRINT"String space needed for the key array is"KLEN*(T2-T1+1) 1768 PRINT"and the available space is"FRE(X$)". 1770 PRINT"This program can't tell whether there is enough space on disk " DD$(5)" for tempo- 1780 PRINT"rary storage of the key array. 1790 PRINT:PRINT"The records will be sorted in "; 1800 IF S8=0 THEN PRINT"ascending ";: GOTO 1820 1810 PRINT"descending "; 1820 IF S6=0 THEN PRINT"alphabetical ";: GOTO 1840 1830 PRINT"numerical "; 1840 PRINT"order." 1850 PRINT: PRINT"The output of the sort will "; 1860 IF P7=0 THEN PRINT"overlay the original file.":GOTO 1880 1870 PRINT"create a new DIMS file "F2$" on disk "DD$(4)"." 1880 PRINT:IF P7=0 AND (T1<>1 OR T2<>N) AND S9=0 THEN PRINT"You are aware that this process will erase records? 1885 IF P7 THEN 1890 ELSE 1900 1890 PRINT"The new file "F2$" will replace the safety copy of "F$". 1892 PRINT"You must then use PIP to move "F2$" to another disk, 1894 PRINT"and use the DEDIT 'backup' command on "F$" to re-create a 1896 PRINT"safety copy. 1900 ' FINAL APPROVAL 1910 PRINT:PRINT"Is this exactly what you want? (y/n) "; 1920 A$=INPUT$(1): IF A$=CHR$(13) THEN A$="y" 1930 PRINT A$ 1940 IF A$="x" THEN 3400 1950 IF A$="n" THEN PRINT"Try again.":GOTO 1090 1960 IF A$<>"y" THEN GOTO 1910 1970 GOTO 2110 1980 ' SORT CONTROLS GUIDE 1990 ' S() array holds key orders (field#, num? (1=num), length, pad?) 2000 ' NK = number of keys specified 2010 ' S6 = 0 alpha sort 2020 ' 1 numeric sort 2030 ' S7 = 0 don't rename dupe file 2040 ' 1 rename dupe file as F2$.D 2050 ' S8 = 0 ascending order 2060 ' 1 descending order 2070 ' S9 = 0 output only sorted range of records 2080 ' 1 output records above and below sorted range 2090 ' P7 = 0 overlay main file 2100 ' 1 output to named file 2110 ' PUT KEYS IN TEMP FILE 2120 GOSUB 4010 2130 PRINT"SORTING '"F$"' 2140 PRINT:PRINT"Extracting keys.":PRINT 2150 OPEN"O",3,DD$(5)+"KEYS.$$$" 2160 FOR I=T1 TO T2 2170 GOSUB 4270:GOSUB 4110 ' get record 2180 IF ASC(T$)=0 THEN X$=CHR$(126)+"(del)":GOTO 2320 ' sorts deletes to end 2190 GOSUB 3540 ' parse 2200 X$="" 2210 FOR X=1 TO NK 2220 IF S(X,3) THEN 2230 ELSE X$=X$+B$(S(X,1)):GOTO 2280 2230 Z$=LEFT$(B$(S(X,1)),S(X,3)) 2240 Y=LEN(Z$) 2250 IF S(X,2)=1 THEN Y$=STRING$(S(X,3)-Y,CHR$(48)): X$=X$+Y$+Z$:GOTO 2280 'pad num field with left 0's 2252 IF S(X,4) THEN 2260 ELSE Y$="":GOTO 2270 2260 Y$=STRING$(S(X,3)-Y,CHR$(32)) 'spaces to pad right 2270 X$=X$+Z$+Y$ 2280 NEXT 2290 IF X$="" THEN X$=CHR$(126):GOTO 2320 ' makes empties go later 2300 IF S6 THEN 2320 2310 GOSUB 3920:X$=Y$ 'ucv 2320 PRINT I,X$ 2330 PRINT#3,X$ 2340 NEXT 2350 CLOSE 3 2360 ' LOAD INDEX AND KEY ARRAYS 2370 PRINT:PRINT"Loading key array:":PRINT 2380 OPEN"I",3,DD$(5)+"KEYS.$$$" 2390 I=T1:J=1:D$(0)=CHR$(0) 2400 IF EOF(3) THEN 2450 2410 LINE INPUT#3,D$(J) 2420 D(J)=I 2430 I=I+1:J=J+1 2440 GOTO 2400 2450 CLOSE 3 2460 KILL DD$(5)+"KEYS.$$$" 2470 ' READY TO SORT ARRAY 2480 PRINT:PRINT"Sorting array.":PRINT 2490 ' from QUICKSORT by Sylvan Rubin DDJ #33 p.42 2500 LND=1:HND=J-1:STP=0 2510 ' PARTITION 2520 GOSUB 4270 'exit 2530 IF LND>=HND THEN 2910 ' pop stack 2540 PRINT CHR$(80);:CTR=INT((LND+HND+1)/2) ' use center for pivot 2550 SWAP D(CTR),D(HND):SWAP D$(CTR),D$(HND) 2560 LO=LND-1:HI=HND 2570 PIV$=D$(HND):GOTO 2600 ' scan-l 2580 ' EXCHANGE 2590 SWAP D(LO),D(HI):SWAP D$(LO),D$(HI) 2600 ' SCAN-L 2610 LO=LO+1:ON S6+1 GOTO 2620,2630 ' alph, num 2620 ON S8+1 GOTO 2640,2650 ' asc, desc 2630 ON S8+1 GOTO 2660,2670 2640 IF D$(LO)PIV$ THEN 2610 ELSE 2680 2660 IF VAL(D$(LO))VAL(PIV$) THEN 2610 ELSE 2680 2680 ' SCAN-H 2690 HI=HI-1:ON S6+1 GOTO 2700,2710 2700 ON S8+1 GOTO 2720,2730 2710 ON S8+1 GOTO 2740,2750 2720 IF D$(HI)>PIV$ THEN 2690 ELSE 2760 2730 IF D$(HI)VAL(PIV$) THEN 2690 ELSE 2760 2750 IF VAL(D$(HI))(HND-LO) THEN 2860 ' stack low 2810 ' STACK HIGH 2820 IF LO+2>HND THEN 2840 2830 STP=STP+1:LST(STP)=LO+1:HST(STP)=HND 2840 ' SHIFT HIGHEND 2850 HND=HI:GOTO 2510 ' partition 2860 ' STACK LOW 2870 IF LND+1>HI THEN 2900 ' shift lowend 2880 STP=STP+1:LST(STP)=LND:HST(STP)=HI 2890 ' SHIFT LOWEND 2900 LND=LO+1:GOTO 2510 ' partition 2910 ' POP STACK 2920 IF STP=0 THEN 2950 ' done 2930 LND=LST(STP):HND=HST(STP) 2940 STP=STP-1:GOTO 2510 ' partition 2950 PRINT:PRINT:PRINT"Array sorted. 2960 ' OUTPUT 2970 NR=0 ' counts number of records in product file 2980 CLOSE 2:KILL DD$(4)+F$+".DD"+FT$:GOSUB 4080 2990 IF S9=0 GOTO 3060 3000 ' COPY BLOCK BELOW T1 3010 IF T1=1 THEN 3060 3020 PRINT:PRINT"Outputting records below range. 3030 FOR I=1 TO T1-1 3040 GOSUB 3430 'output record 3050 NEXT 3060 ' MOVE RECORDS PER INDEX ARRAY 3070 PRINT:PRINT"Now moving records from " DD$(3)" to "DD$(4)" in sorted order per index array.":PRINT 3080 ERASE D$ ' don't need strings 3090 FOR J=1 TO T2-T1+1 3100 I=D(J):GOSUB 3430 3110 NEXT 3120 ' COPY BLOCK ABOVE 3130 IF S9=0 OR T2=N THEN 3180 ' skip block copy 3140 PRINT:PRINT"Outputting records above range 3150 FOR I=T2+1 TO N 3160 GOSUB 3430 ' output 3170 NEXT 3180 ' SAVE HEADER AND TIDY UP 3190 PRINT:PRINT"Saving header;"NR"records 3200 T$="" 3210 I=0 3220 I=I+1 3230 T$=T$+N$(I)+CHR$(126) 3240 IF LEFT$(N$(I),4)="stop" THEN 3260 3250 GOTO 3220 3260 T$=T$+STR$(NR)+CHR$(126) ' NR at end 3270 NR=0 ' for header 3280 GOSUB 3470 ' put it 3290 PRINT"!" 3300 IF P7 THEN 3330 'rename product 3310 GOSUB 3620 ' copy dupe to main 3320 GOTO 3380 3330 ' RENAME OUTPUT FILE 3340 CLOSE 2:NAME DD$(4)+F$+".DD"+FT$ AS DD$(4)+F2$+".D"+FT$:GOSUB 4080 3350 PRINT"Product file "F2$" is now on disk "DD$(4)" (backup erased). 3360 PRINT"After moving product to desired disk, use 'backup' command on "F$ 3370 INPUT"to restore safety copy. Hit RETURN to continue. ";A$ 3380 PRINT:PRINT:PRINT"Sort completed 3390 PRINT CHR$(7); 'beep 3400 ' RETURN TO DEDIT 3410 PRINT:PRINT"Re-loading DEDIT. 3420 CHAIN DD$(1)+"DEDIT",1000 3430 ' (SUB) OUTPUT RECORD "I" 3440 GOSUB 4110:PRINT T$ ' get rec I 3450 GOSUB 4270 ' exit 3460 NR=NR+1 ' # records in prod. file 3470 ' PUT RECORD NR 3480 ON FT GOTO 3510,3490 3490 LSET S$=MID$(T$,129) 3500 PUT #2,FT*NR+2 3510 LSET S$=LEFT$(T$,128) 3520 PUT #2,FT*NR+1 3530 RETURN 3540 ' (SUB) PARSE STRING 3550 K=0 3560 J=INSTR(T$,CHR$(126)) ' delimiter 3570 IF J=0 THEN RETURN 3580 K=K+1 3590 B$(K)=MID$(T$,1,J-1) 3600 T$=MID$(T$,J+1) 3610 GOTO 3560 3620 ' (SUB) ERASE ORIGINAL FILE AND COPY DUP TO ORIG 3630 CLOSE 3640 PRINT 3650 KILL DD$(3)+F$+".D"+FT$ 3660 PRINT"Copying dupe, overlaying original file.":PRINT 3670 GOSUB 4040 ' open both files 3680 FOR J=1 TO FT*(N+1) 3690 GET #2,J 3700 PRINT"&"; 3710 LSET R$=S$ 3720 PUT #1,J 3730 PRINT"*"; 3740 NEXT J 3750 RETURN 3760 ' ERROR HANDLING 3770 IF ERR=61 THEN RESUME 3780 ELSE 3810 3780 PRINT"Sorry - process halted because there isn't enough disk space 3790 PRINT"for the key file. 3800 INPUT"Hit return to recover.";A$:CLOSE:T=8:CHAIN DD$(1)+"DIMS",1000 3810 IF ERR=7 OR ERR=14 THEN RESUME 3820 ELSE 3850 3820 PRINT"Sorry - process halted because key array needed more memory 3830 PRINT"than is available. Try again with shorter key specifications. 3840 INPUT"Hit return to try again.";A$:GOTO 1090 3850 IF ERR=58 THEN RESUME 3860 ELSE 3910 3860 PRINT"Sorry - file named "F2$" already exists. 3870 INPUT"Enter another name for the output file here: ";X$ 3880 IF X$="" THEN 3870 3890 GOSUB 3920:F2$=Y$ 'ucv 3900 GOTO 3330 3910 ON ERROR GOTO 0 3920 ' (SUB) UCV 3930 Y$="" 3940 FOR J=1 TO LEN(X$) 3950 Y$=Y$+" " 3960 X=ASC(MID$(X$,J,1)) 3970 IF 96CHR$(27) THEN RETURN 4290 PRINT:PRINT"Process paused by ESCAPE from keyboard. 4300 PRINT"Do you want to continue (y,n or x) ? "; 4310 A$=INPUT$(1):IF A$=CHR$(13) THEN A$="y" 4320 PRINT A$:IF A$="x" THEN CLOSE 3:GOTO 3400 4330 IF A$<>"y" THEN CLOSE 3:GOTO 1090 4340 RETURN  A$=CHR$(13) THEN A$="y" 4320 PRINT A$:IF A$="x" THEN CLOSE 3:GOTO