home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Between Heaven & Hell 2
/
BetweenHeavenHell.cdr
/
300
/
245
/
brekdown.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-12-18
|
32KB
|
798 lines
{$C-,R-,V-}
{ BREAK DOWN -- a text analysis and generation program
copyright 1985 by Neil J. Rubenking
based on the program TRAVESTY, from the Nov. 1984 BYTE magazine
NOTE that the "KEY" that indexes the DATA files is not included in the
DATA files. This saves about 20% on the DATA file size, and that 20%
can be important. It also means that you cannot restore a "corrupted"
INDEX file, but that's not likely to be a problem. Also note that the
KEY values in the INDEX file always take MaxKeyLen+1 bytes, even if the
"order" is smaller. If you want to try orders greater than 8, change
the value of MaxKeyLen and recompile.
}
program BreakDown;
const
outCharNum = 34; { If you change the number of characters tracked,
you will have to change this constant. }
MaxKeyLen = 7; { MaxKeyLen is one less that the maximum order. }
lineWidth = 55; { lines less than this length will be considered
to have ended "early", with a hard <CR> }
{TURBO-Access constants}
const
MaxDataRecSize = OutCharNum;
PageSize = 48; { You can experiment with these }
Order = 24; { constants, which are described }
PageStackSize = 16; { in not-quite-enough detail in }
MaxHeight = 8; { the TURBO TOOLBOX manual }
{$I access.box}
{$I getkey.box}
{$I AddKey.box}
{$I DelKey.box}
type
char_set = set of char;
choices = array[1..outCharNum] of byte;
line = string[90];
chunkString = string[MaxKeyLen];
filename_type = string[14];
var
Breakout, worked : boolean;
ordr, N, co : byte;
chars_to_output, KeyNum, Totl_to_out, counter, AllRecs : integer;
ShowRecs : real;
Ch, OutDrive, InxDrive, DatDrive : char;
outChars : string[40];
source, outFile, BSource : text;
sourceName, DatName, OutName, InxName, OldName,
BSourceName, BDatName, BInxName : filename_type;
OkayChars, PuncChars, NumbChars : char_set;
sourceLine : line;
NoChance, AR, BR : choices;
lookChunk : chunkString;
DatF, BDatF : datafile; {TOOLBOX types}
IndexF, BIndexF : IndexFile; {TOOLBOX types}
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure BreakMessage; external 'BREK2.TXT';
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure PlayMessage(offset : integer);
var N : integer;
begin
N := 0;
repeat
write(chr(MEM[CSeg:Offset + N]));
N := N + 1;
until MEM[CSeg:N+Offset] = $1A;
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
function rep(CH : char ; BY : byte):line;
var
temp : line; { "rep" produces a string of BY repetitions of }
N : byte; { the character CH. }
begin
temp := '';
for N := 1 to BY do
temp := temp + CH;
rep := temp;
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure RevVideo;
begin
textColor(black);
textBackGround(white);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
function LowCase(CC : char):char;
begin
if CC in ['A'..'Z'] then LowCase := chr(ord(CC)+32)
else LowCase := CC;
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure DoHeader(act1, AFile, act2, BFile : filename_type);
begin
ClrScr; { This produces a header that tells}
RevVideo; { what BREAK DOWN is doing, with a }
Write(#218,rep(#196,78),#191,#179); { reverse-video box around it. }
HighVideo;
write(' BREAK DOWN is now ',act1,' ',AFile,act2,BFile);
write(rep(' ',49-length(AFile)-length(act1)-length(act2)-length(BFile)));
write('ORDER ',ordr:2);
RevVideo;
write(#179,#212,rep(#205,78),#190);
HighVideo;
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
function exists(ThisFile : filename_type):boolean;
var
tempFile : text; {We can get away with assigning a text file to ANY
filename because we aren't going to do any input/output}
begin
assign(tempFile,ThisFile);
{$I-} { Here we set I/O error checking }
reset(tempFile); { OFF and do a RESET. If the file }
{$I+} { exists, there's no error, and }
if IOResult = 0 then exists := true { IOResult = 0. If not, IOResult }
else exists := false; { holds the error number. }
close(tempFile);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure Process(VAR FromName, ToName : filename_type;
drive : char;
ext : chunkString);
begin
if ordr < 10 then { If the order is 9 or less, put that }
ext[3] := chr(48+ordr) { digit in the middle of the extension.}
else ext[3] := chr(55+ordr); { For 10 and up, use A, B, C, &c. }
ToName := FromName;
if pos('.',ToName) <> 0 then { IF an extension is included, }
delete(ToName,pos('.',ToName),4); { delete it. Then add the new }
ToName := ToName + ext; { extension. }
if UpCase(drive) in ['A'..'Z'] then {IF the drive character is valid, then}
if pos(':',ToName) <> 0 then { if a drive has been specified,}
ToName[1] := drive { just change the first char -- }
else ToName := drive + ':' + ToName; { else add drive and ':' }
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure initialize(mode : char);
{ modes are M for Make a new file,
O for Open an existing file,
G for (Open a file and) Generate,
B for Open another existing file }
{ The procedures SetUp and SetUpB exist solely for the purpose of
breaking up the action into graspable chunks. }
{==========================================================================}
procedure SetUp;
begin
if (exists(sourceName)) or (mode = 'O') then
begin
process(sourceName, DatName, DatDrive, '.DAT');
case mode of
'M': MakeFile( DatF, DatName, OutCharNum);
'O': OpenFile( DatF, DatName, OutCharNum);
end;
if OK then
begin
process(sourceName, InxName, InxDrive, '.INX');
case mode of
'M': MakeIndex(IndexF,InxName,MaxKeyLen,0);
'O': OpenIndex(IndexF,InxName,MaxKeyLen,0);
end;
if not OK then
case mode of
'M': writeLn('Cannot create index file');
'O': WriteLn('Index file does not exist');
end;
end
else
case mode of
'M': writeLn('Cannot create data file');
'O': WriteLn('Data file does not exist');
end;
worked := OK;
end { if exists }
else
begin
WriteLn('Source file does not exist.');
worked := false;
end;
end;
{==========================================================================}
procedure SetUpB;
begin
process(BsourceName, BDatName, DatDrive, '.DAT');
OpenFile( BDatF, BDatName, OutCharNum);
if OK then
begin
process(BsourceName, BInxName, InxDrive, '.INX');
OpenIndex(BIndexF,BInxName,MaxKeyLen,0);
if not OK then
WriteLn('Secondary Index file does not exist');
end
else
WriteLn('Secondary Data file does not exist');
worked := OK;
end;
{==========================================================================}
begin
mode := upCase(mode);
if mode = 'B' then WriteLn('Name of second source file: ')
else WriteLn(' Name of main source file: ');
WriteLn(' Drive for DATA file: ');
WriteLn(' Drive for INDEX file: ');
if mode = 'G' then
WriteLn(' Drive for output: ')
else WriteLn;
DatDrive := ' '; InxDrive := ' '; outDrive := ' ';
GotoXY(29,WhereY-4);
if mode = 'B' then read(BsourceName)
else
begin
Read(sourceName);
if sourceName = '' then { If you just hit <return> when }
begin { prompted for a SourceName, }
if OldName <> '' then { the default is whatever the }
begin { most recent previous name was.}
sourceName := OldName;
GotoXY(29,WhereY);
write(sourceName);
end;
end
else
OldName := SourceName;
end;
{ The data file for fff.xxx will be }
GotoXY(29,WhereY+1); { called fff.DnT, where n is the }
read(DatDrive); { order of the BreakDown. The index }
GotoXY(29,WhereY+1); { will be fff.InX, and any output }
read(InxDrive); { file will be fff.OnT }
if mode = 'G' then { If the order is 10 or more, "n" }
begin { will be a letter, starting with }
GotoXY(29,WhereY+1); { A for 10. }
read(outDrive);
end;
WriteLn; { The source file only has}
if mode = 'G' then mode := 'O'; { to be present if we're }
{ [M]aking a new BreakDown}
if mode = 'B' then SetUpB
else SetUp;
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure Merge;
var
RC, matches : real;
BRecNum, ARecNum : integer;
{==========================================================================}
procedure Combine(VAR AA,BB : choices);
begin
if CH = 'C' then
begin
for co := 1 to outCharNum do
begin
if AA[co] + BB[co] > 0 then
if AA[co] + BB[co]*RC < 255.0 then
AA[co] := AA[co] + (trunc(BB[co]*RC) and $FF)
else AA[co] := $FF;
end;
end
else
begin
for co := 1 to OutCharNum do
begin
if AA[co] + BB[co] > 0 then
if AA[co] + BB[co] < $FF then
AA[co] := AA[co] + BB[co]
else AA[co] := $FF;
end;
end;
end;
{==========================================================================}
procedure GetConstant;
begin
repeat
GotoXY(1,WhereY); ClrEOl;
Write('Multiply by what constant? (0.01 to 100)');
read(RC);
until (RC > 0.01) and (RC <= 100 );
end;
{==========================================================================}
procedure DoMerge;
var
BOK : boolean;
begin
AllRecs := UsedRecs(BDatF);
ShowRecs := AllRecs;
if ShowRecs < 0 then ShowRecs := ShowRecs + 65536.0;
if CH = 'C' then GetConstant
else RC := 1.0;
ClrScr;
ClearKey(BIndexF); { NextKey after ClearKey gives us }
NextKey(BIndexF,BRecNum,lookChunk); { the very first key. }
BOK := OK;
counter := 1;
matches := 0;
GetRec(BDatF,BRecNum,BR); { We Get the Record corresponding }
while BOK do { to that first key. }
begin
if counter mod 10 = 0 then
begin
GotoXY(1,1);CLrEOL;
write(counter:6,' out of ',ShowRecs:6:0);
end;
FindKey(IndexF,ARecNum,lookChunk);
if OK then { If that same key is in the }
begin { index of the file into which }
matches := matches + 1; { we're merging, combine the }
GetRec(DatF,ARecNum,AR); { frequency tables and write }
combine(AR,BR); { combined table back to disk. }
PutRec(DatF,ARecNum,AR); { . . .}
end
else
begin
AddRec(DatF,ARecNum,BR); { Otherwise, Add the Record }
AddKey(IndexF,ARecNum,LookChunk); { and its Key. }
end;
NextKey(BIndexF,BRecNum,LookChunk); { Get the next key, . . .}
BOK := OK;
GetRec(BDatF,BRecNum,BR); { . . . and its record, }
counter := counter + 1; { and increment the counter. }
end;
CloseFile(DatF);
CloseFile(BDatF);
CloseIndex(IndexF);
CloseIndex(BIndexF);
end;
{==========================================================================}
begin
GotoXY(1,1);
DelLine;
WriteLn('MERGING');
initialize('O');
if worked then
initialize('B');
if worked then
begin
ClrScr;
DoHeader('merging',BSourceName,' into ',SourceName);
window(1,4,80,25);
ClrScr;
WriteLn(SourceName,'''s DAT and INX files will be permanently changed. You can');
WriteLn('multiply the frequencies of ',BSourceName,' by a constant from 1/100 to');
WriteLn('100, though a non-zero frequency will never be reduced to zero, nor will');
WriteLn('it grow larger than 255.');
WriteLn;
WriteLn('[G]o ahead, set a multiplying [C]onstant, or [Q]uit?');
repeat
read(Kbd,CH);
until UpCase(CH) in ['G','C','Q'];
CH := UpCase(CH);
if CH <> 'Q' then DoMerge;
end;
WriteLn;
writeLn(matches:1:0,' records matched existing records in ',DatName);
WriteLn('Press a key to return to main menu.');
repeat until Keypressed; Read(Kbd);
window(1,1,80,25);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure Analyze;
var
NumOver : integer;
OldRecs, MadeRecs : real;
{==========================================================================}
procedure ReadSource;
var
HoldThatLine : Line;
linePos : byte;
NxCh : char;
{------------------------------------------------------------------}
procedure CleanUp(VAR aLine : line);
var
shortLine : boolean;
begin
while pos(#9,aLine) <> 0 do { Replace TABs with five }
begin { spaces. This is just for}
insert(' ',aLine,pos(#9,aLine)); { measuring line length. }
delete(aLine,pos(#9,aLine),1);
end;
if length(aLine) < lineWidth then { If the line is "short", then we }
shortLine := true { suppose it to end with a HARD }
else ShortLine := false; { Carriage Return (end paragraph).}
for co := 1 to length(aLine) do
begin
if aLine[co] in OkayChars then { Okay characters get converted}
aLine[co] := LowCase(aLine[co]) { to lower case. }
else
if aLine[co] = '"' then { Double quotes turn into single}
aLine[co] := #39
else
if aLine[co] in PuncChars then {Punctuation that is "not Okay" }
aLine[co] := ' ' {gets spaced out. It is treated }
{separately because you might }
{want to convert all punctuation}
{into, say, commas. }
else
if aLine[co] in NumbChars then { Numbers turn into # symbols}
aLine[co] := '#'
else aLine[co] := ' '; { Anything else is spaced out.}
end;
while pos(' ',aLine) <> 0 do { Eliminate multiple spaces }
delete(aLine,pos(' ',aLine),1);
while pos('##',aLine) <> 0 do { Reduce numbers to a single "#"}
delete(aLine,pos('##',aLine),1);
while pos(' ,',aLine) <> 0 do { Eliminate spaces AHEAD of commas}
delete(aLine,pos(' ,',aLine),1);
while pos(' .',aLine) <> 0 do { . . . and periods }
delete(aLine,pos(' .',aLine),1);
aLine := ' ' + aLine;
if (ShortLine) or (aLine = ' ') then { Add a paragraph symbol to }
aLine := aLine + #20; { the end of any short lines.}
end;
{------------------------------------------------------------------}
procedure FeedIn(aLine : line);
begin
repeat
NxCh := aLine[linePos]; { Locate the NEXT character. }
FindKey(IndexF, KeyNum, LookChunk); { See if the current "chunk" }
{ is already on record. }
if OK then { If it is, call up its record}
begin { and add one to the chances }
GetRec(DatF,KeyNum,AR); { of it begin followed by NxCh}
{ UNLESS the chances }
if AR[pos(NxCh,outChars)] < $FF then { for NxCh are at the}
AR[pos(NxCh,outChars)] := { max of 255 already.}
AR[pos(NxCh,outChars)] + 1
else NumOver := NumOver + 1;
PutRec(DatF,KeyNum,AR);
end
else
begin
{If the "chunk" was not on}
{ record yet, create it, }
AR := NoChance; { set all the chances to }
AR[pos(NxCh,outChars)] := 1; { zero, and set the NxCh }
{ chance to one. }
AddRec(DatF,KeyNum,AR);
AddKey(IndexF,KeyNum,LookChunk);
end;
LookChunk := copy(LookChunk,2,ordr-2); {Now drop the first char}
LookChunk := LookChunk + NxCh; {of the chunk, add the NxCh}
LinePos := LinePos + 1; {to it, and advance the LinePos}
until (LinePos > length(aLine)); { Do it until the whole line is in,}
LinePos := 1; { then reset the LinePos. }
end;
{------------------------------------------------------------------}
begin
NumOver := 0;
reset(source);
ReadLn(source,sourceLine);
CleanUp(sourceLine);
while length(sourceLine) < ordr do { To start, we must be sure }
begin { to have a line long enough}
ReadLn(source,HoldThatLine); { to extract a "chunk" from.}
sourceLine := sourceLine + HoldThatLine;
CleanUp(sourceLine);
end;
WriteLn(sourceLine);
LookChunk := copy(sourceLine,1,ordr-1); { Extract the first chunk, and}
HoldThatLine := LookChunk; { save it to tack on the end. }
linePos := ordr;
NxCh := sourceLine[LinePos];
FeedIn(sourceLine);
BreakOut := false;
while (not EOF(source)) and (not breakout) do
begin
ReadLn(source,sourceLine);
CleanUp(sourceLine);
WriteLn(sourceLine);
FeedIn(sourceLine);
if keypressed then BreakOut := true; { The BreakDown can take a long
time -- if you press a key,
the program shuts down grace-
fully, without losing what it
has done. }
end;
FeedIn(HoldThatLine);
WriteLn(HoldThatLine);
WriteLn; WriteLn;
Write('Successfully read in ',sourceName);
MadeRecs := UsedRecs(DatF);
if MadeRecs < 0 then MadeRecs := 65536. + MadeRecs;
if upCase(CH) = 'N' then
WriteLn(' Produced ',MadeRecs:1:0,' records.')
else WriteLn(' Added ',(MadeRecs - OldRecs):1:0,' records.');
if NumOver > 0 then
WriteLn(NumOver,' entries have hit the max of 255.');
CloseFile(DatF);
CloseIndex(IndexF);
end;
{==========================================================================}
begin
GotoXY(1,1);
DelLine;
WriteLn('»»ANALYZING««');
WriteLn;
WriteLn('[N]ew source, or [A]dd to existing?');
repeat
read(Kbd,CH);
until upCase(CH) in ['N','A'];
case upCase(CH) of
'N': begin
initialize('M');
assign(source,sourceName);
end;
'A': begin
Write('Name of NEW source: ');
ReadLn(sourceName);
assign(source,sourceName);
initialize('O');
OldRecs := UsedRecs(DatF);
if OldRecs < 0 then OldRecs := 65536. + OldRecs;
end;
end;
if worked then
begin
DoHeader('analyzing',sourceName,'','');
window(1,4,80,25);
GotoXY(1,1);
ReadSource;
end;
WriteLn('Press a key to return to main menu.');
repeat until keypressed; Read(Kbd);
window(1,1,80,25);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure Generate;
{==========================================================================}
procedure WriteTravesty;
label
PunkOut;
var
NxCh : char;
aRecNum : integer;
RealTot, rando : real;
NextCap, Done, Nearly : boolean;
{------------------------------------------------------------------}
procedure CheckForCapsAndLineEnd;
begin
if NextCap then
if NxCh in ['a'..'z'] then { If we're waiting to capitalize, do }
begin { it only to an alphabetic character.}
NxCh := UpCase(NxCh);
NextCap := false;
end;
if NxCh in ['.','?'] then { Capitalize the next ALPHA character }
NextCap := true; { after a . or a ? }
if NxCh = #20 then
begin { If you hit a paragraph marker, }
WriteLn(OutFile,SourceLine); { end the line and print it out. }
writeLn(SourceLine);
SourceLine := '';
NextCap := true; { Capitalize the first char of the new line.}
end
else
begin
SourceLine := SourceLine + NxCh;
if (outChars[N] = ' ') and (length(SourceLine) > lineWidth) then
begin
WriteLn(OutFile,SourceLine); { End a line at the next space }
writeLn(SourceLine); { after max line width is reached. }
SourceLine := '';
end;
end; { all about whether to end the line}
if Nearly then { "Nearly" means that the max char }
if NxCh = ' ' then { count has been reached. As soon }
begin { as we hit a space, we're done. }
done := true; { For good looks, we append a final}
SourceLine := SourceLine + '.'; { period. }
end;
if keypressed then BreakOut := true;
end;
{------------------------------------------------------------------}
begin
Assign(outFile, outName); { We can't directly get the }
ReWrite(outFile); { KEY for a given record #, }
lookChunk := ' ' + chr(trunc(random(26))+97);{ so we use SearchKey, which}
SearchKey(IndexF,aRecNum,lookChunk); { returns the KEY and # of }
repeat { first entry that's >= the }
NextKey(IndexF,aRecNum,LookChunk); { string supplied. Then we }
until LookChunk[1] = ' '; { NextKey 'til we find a }
SourceLine := LookChunk; { suitable one. }
SourceLine[2] := upCase(SourceLine[2]); { Capitalize the first letter . . .}
Totl_to_out := ordr-1;
NextCap := false;
randomize;
Breakout := false;
Nearly := false;
Done := false;
while (not DONE) and (not BreakOut) do
begin
Totl_to_out := Totl_to_out + 1;
if totl_to_out = chars_to_output then { When the max is hit, set }
Nearly := true; { "nearly" to true. At the}
RealTot := 0; { next space, you're DONE }
FindKey(IndexF,KeyNum,LookChunk);
if OK then
begin
GetRec(DatF,KeyNum,AR);
for N := 1 to outCharNum do { Total up all the }
RealTot := RealTot + AR[N]; { "chances" figures }
end
else
begin { This should never happen, but }
WriteLn(SourceLine,'<<<'); { just in case . . . }
Write(chr(7));
WriteLn('Didn''t find record of string >',LookChunk,'<');
Goto punkOut;
end;
rando := random*RealTot; { Select a random number less than total}
N := 0; { and "count off" chances until you use }
repeat { it up -- that's the next character. }
N := N + 1;
RealTot := RealTot - AR[N];
until (RealTot < rando) or (N > outCharNum);
if N > length(outChars) then { This should never happen! }
begin
writeLn(chr(7),chr(7),'Error in chances table for >',LookChunk,'<');
Goto PunkOut;
end;
delete(LookChunk,1,1); { Knock off the first character of the}
NxCh := outChars[N]; { current chunk, and tack on the newly}
LookChunk := LookChunk + NxCh; { chosen next character. }
CheckForCapsAndLineEnd;
end; { of the big WHILE }
WriteLn(OutFile,SourceLine); { Be sure to write the very last line! }
writeLn(SourceLine);
WriteLn; WriteLn;
Write('total number of chars output ',Totl_to_out);
WriteLn(' of requested ',chars_to_output);
PunkOut:
close(outFile);
closeFile(datF);
closeIndex(indexF);
end;
{==========================================================================}
begin
GotoXY(1,1);
DelLine;
WriteLn('»»GENERATING««');
WriteLn;
initialize('G');
if worked then
begin
Write('How many characters to output?');
read(chars_to_output);
process(sourceName,outName, outDrive, '.OUT');
DoHeader('generating',OutName,'','');
window(1,4,80,25);
GotoXY(1,1);
WriteTravesty;
end;
WriteLn('Press a key to go back to menu.');
repeat until keypressed; Read(Kbd);
window(1,1,80,25);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
procedure List;
{==========================================================================}
procedure DoList;
label
enough;
var
M : integer;
StrRecs : filename_type;
begin
Write('View a particular record?');
read(CH); WriteLn;
if upCase(CH) = 'Y' then
begin
WriteLn('Which ',ordr-1,'-letter sequence?');
lookChunk := '';
for N := 1 to ordr-1 do
begin
repeat
read(Kbd,CH);
until pos(CH,outChars) <> 0;
write(CH);
lookChunk := lookChunk + CH;
end;
FindKey(IndexF,M,lookChunk);
if not OK then
begin
Write(chr(7),'"',lookChunk,'" is not in this list.');
ClearKey(IndexF);
NextKey(IndexF,M,lookChunk);
end;
end
else
begin
ClearKey(IndexF);
NextKey(IndexF,M,LookChunk);
end;
AllRecs := UsedRecs(DatF);
ShowRecs := AllRecs;
if ShowRecs < 0 then ShowRecs := ShowRecs + 65536.0;
str(ShowRecs:1:0,StrRecs);
StrRecs := ': ' + StrRecs;
DoHeader('listing',DatName,StrRecs,' records.');
textcolor(LightBlue); { Blue = underlined on many mono monitors. }
write(rep(' ',ordr+1)); { Here we write a heading line. }
for N := 1 to outCharNum do
write(outChars[N]:2);
WriteLn;
window(1,5,80,25);
GotoXY(1,1);
co := 0;
while OK do
begin
co := co + 1;
GetRec(DatF,M,AR); { Get each record and show }
{ the chunk it represents, }
Write('|',LookChunk:(ordr-1),'|'); { along with its chances. }
for N := 1 to outCharNum do
if AR[N] <> 0 then write(AR[N]:2)
else write(' ');
WriteLn;
if co >= 20 then
begin
write('Press a key to see more--or [Q]uit');
repeat until keypressed;
read(Kbd,CH);
if upCase(CH) = 'Q' then GoTo enough;
ClrScr;
co := 0;
end;
NextKey(IndexF,M,LookChunk); { Go thru the list in order by taking
the Next Key again and again. }
end; {while}
Enough:
CH := ' ';
textColor(white);
end;
{==========================================================================}
begin
GotoXY(1,1);
DelLine;
WriteLn('»»LISTING««');
WriteLn;
initialize('O');
if worked then DoList;
Write('Press a key to return to main menu.');
repeat until Keypressed; Read(Kbd);
window(1,1,80,25);
end;
{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
begin
PuncChars := ['!'..'&','('..'+',':'..'>','['..'`','{'..'~','@','/'];
NumbChars := ['0'..'9'];
OkayChars := ['a'..'z','-',#39,'A'..'Z','.',',','?'];
Outchars := 'abcdefghijklmnopqrstuvwxyz -.,?#' + #20 + #39;
{ NOTICE: if you add a char to OutChars, change the constant OutCharNum }
for N := 1 to OutCharNum do noChance[N] := 0;
ClrScr;
PlayMessage(ofs(BreakMessage));
repeat until keypressed;
Read(Kbd);
oldName := '';
ClrScr;
repeat
InitIndex;
ClrScr;
RevVideo;
Write('[A]nalyze a text, [G]enerate a travesty, [L]ist, [M]erge,');
WriteLn(' or [Q]uit?');
HighVideo;
repeat
read(Kbd,CH);
until upCase(Ch) in ['A','G','L','M','Q'];
if UpCase(CH) <> 'Q' then
begin
repeat
Write('What "order"? (3..',MaxKeyLen+1,') ');
read(ordr);
until ordr in [3..MaxKeyLen+1]; { if you just hit <return> here, the
most recent "order" will be used.}
DelLine;
end;
case upCase(ch) of
'A': Analyze;
'M': Merge;
'G': Generate;
'L': List;
end;
until upCase(ch) = 'Q';
end.