home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
USCX
/
TPCOMPLT.ZIP
/
LISTMAN.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-05-05
|
10KB
|
326 lines
{--------------------------------------------------------------}
{ ListMan }
{ }
{ Mailing list manager demo using dynamic (heap) storage }
{ }
{ by Jeff Duntemann }
{ Turbo Pascal V3.0 }
{ Last update 2/1/86 }
{ }
{ From the book, COMPLETE TURBO PASCAL, by Jeff Duntemann }
{ Scott, Foresman & Co. (c) 1986,1987 ISBN 0-673-18600-8 }
{--------------------------------------------------------------}
PROGRAM ListMan;
TYPE
String30 = String[30]; { Using derived string types }
String6 = String[6]; { makes type NAPRec smaller }
String3 = String[3];
NAPPtr = ^NAPRec;
NAPRec = RECORD
Name : String30;
Address : String30;
City : String30;
State : String3;
Zip : String6;
Next : NAPPtr { Points to next NAPRec }
END; { in a linked list }
NAPFile = FILE OF NAPRec;
VAR
Ch : Char;
Root : NAPPtr;
Quit : Boolean;
{$I YES.SRC } { Contains Yes }
PROCEDURE ClearLines(First,Last : Integer);
VAR
I : Integer;
BEGIN
FOR I := First TO Last DO
BEGIN
GotoXY(1,I);
ClrEOL
END
END;
PROCEDURE ShowRecord(WorkRec : NAPRec);
VAR
I : Integer;
BEGIN
ClearLines(17,22); { Clear away anything in that spot before }
GotoXY(1,17);
WITH WorkRec DO
BEGIN
Writeln('>>Name: ',Name);
Writeln('>>Address: ',Address);
Writeln('>>City: ',City);
Writeln('>>State: ',State);
Writeln('>>Zip: ',Zip)
END
END;
PROCEDURE CheckSpace;
VAR
Space : Integer;
RealRoom : Real;
RecordRoom : Real;
BEGIN
Space := MemAvail; { MemAvail returns negative Integer for }
{ space larger than 32,767. Convert }
{ (to a real) by adding 65536 if negative }
IF Space < 0 THEN RealRoom := 65536.0 + Space ELSE RealRoom := Space;
RealRoom := RealRoom * 16; { Delete this line for Z80 versions! }
{ MemAvail for 8086 returns 16-byte }
{ paragraphs, not bytes!! }
RecordRoom := RealRoom / SizeOf(NAPRec);
ClearLines(2,3);
Writeln('>>There is now room for ',RecordRoom:6:0,' records in your list.');
END;
PROCEDURE ListDispose(VAR Root : NAPPtr);
VAR
Holder : NAPPtr;
BEGIN
GotoXY(27,10); Write('>>Are you SURE? (Y/N): ');
IF YES THEN
IF Root <> Nil THEN
REPEAT
Holder := Root^.Next; { First grab the next record... }
Dispose(Root); { ...then dispose of the first one... }
Root := Holder { ...then make the next one the first }
UNTIL Root = Nil;
ClearLines(10,10);
CheckSpace
END;
PROCEDURE AddRecords(VAR Root : NAPPtr);
VAR
I : Integer;
Abandon : Boolean;
WorkRec : NAPRec;
Last : NAPPtr;
Current : NAPPtr;
BEGIN
GotoXY(27,7); Write('<<Adding Records>>');
REPEAT { Until user answers 'N' to "MORE?" question... }
ClearLines(24,24);
FillChar(WorkRec,SizeOf(WorkRec),CHR(0)); { Zero the record }
ClearLines(9,15);
GotoXY(1,9);
WITH WorkRec DO { Fill the record with good data }
BEGIN
Write('>>Name: '); Readln(Name);
Write('>>Address: '); Readln(Address);
Write('>>City: '); Readln(City);
Write('>>State: '); Readln(State);
Write('>>Zip: '); Readln(Zip)
END;
Abandon := False;
{ Here we traverse list to spot duplicates: }
IF Root = Nil THEN { If list is empty point Root to record }
BEGIN
New(Root);
WorkRec.Next := Nil; { Make sure list is terminated by Nil }
Root^ := WorkRec;
END
ELSE { ...if there's something in list already }
BEGIN
Current := Root; { Start traverse at Root of list }
REPEAT
IF Current^.Name = WorkRec.Name THEN { If duplicate found }
BEGIN
ShowRecord(Current^);
GotoXY(1,15);
Write
('>>The record below duplicates the above entry''s Name. Toss entry? (Y/N): ');
IF Yes THEN Abandon := True ELSE Abandon := False;
ClearLines(15,22)
END;
Last := Current;
Current := Current^.Next
UNTIL (Current = Nil) OR Abandon OR (Current^.Name > WorkRec.Name);
IF NOT Abandon THEN { Add WorkRec to the linked list }
IF Root^.Name > WorkRec.Name THEN { New Root item! }
BEGIN
New(Root); { Create a new dynamic NAPRec }
WorkRec.Next := Last; { Point new record at old Root }
Root^ := WorkRec { Point new Root at WorkRec }
END
ELSE
BEGIN
NEW(Last^.Next); { Create a new dynamic NAPRec, }
WorkRec.Next := Current; { Points its Next to Current }
Last^.Next^ := WorkRec; { and assign WorkRec to it }
CheckSpace { Display remaining heapspace }
END;
END;
GotoXY(1,24); Write('>>Add another record to the list? (Y/N): ');
UNTIL NOT Yes;
END;
PROCEDURE LoadList(VAR Root : NAPPtr);
VAR
WorkName : String30;
WorkFile : NAPFile;
Current : NAPPtr;
I : Integer;
OK : Boolean;
BEGIN
Quit := False;
REPEAT
ClearLines(10,10);
Write('>>Enter the Name of the file you wish to load: ');
Readln(WorkName);
IF Length(WorkName) = 0 THEN { Hit (CR) only to abort LOAD }
BEGIN
ClearLines(10,12);
Quit := True
END
ELSE
BEGIN
Assign(WorkFile,WorkName);
{$I-} Reset(WorkFile); {$I+}
IF IOResult <> 0 THEN { 0 = OK; 255 = File Not Found }
BEGIN
GotoXY(1,12);
Write('>>That file does not exist. Please enter another.');
OK := False
END
ELSE OK := True { OK means File Is open }
END
UNTIL OK OR Quit;
IF NOT Quit THEN
BEGIN
ClearLines(10,12);
Current := Root;
IF Root = Nil THEN { If list is currently empty }
BEGIN
NEW(Root); { Load first record to Root^ }
Read(WorkFile,Root^);
Current := Root
END { If list is not empty, find the end: }
ELSE WHILE Current^.Next <> Nil DO Current := Current^.Next;
IF Root^.Next <> Nil THEN { If file contains more than 1 record }
REPEAT
NEW(Current^.Next); { Read and add records to list }
Current := Current^.Next; { until a record's Next field }
Read(WorkFile,Current^) { comes up Nil }
UNTIL Current^.Next = Nil;
CheckSpace;
Close(WorkFile)
END
END;
PROCEDURE ViewList(Root : NAPPtr);
VAR
I : Integer;
WorkFile : NAPFile;
Current : NAPPtr;
BEGIN
IF Root = Nil THEN { Nothing is now in the list }
BEGIN
GotoXY(27,18);
Writeln('<<Your list is empty!>>');
GotoXY(26,20);
Write('>>Press (CR) to continue: ');
Readln
END
ELSE
BEGIN
GotoXY(31,7); Write('<<Viewing Records>>');
Current := Root;
WHILE Current <> Nil DO { Traverse and display until Nil found }
BEGIN
ShowRecord(Current^);
GotoXY(1,23);
Write('>>Press (CR) to view Next record in the list: ');
Readln;
Current := Current^.Next
END;
ClearLines(19,22)
END
END;
PROCEDURE SaveList(Root : NAPPtr);
VAR
WorkName : String30;
WorkFile : NAPFile;
Current : NAPPtr;
I : Integer;
BEGIN
GotoXY(1,10);
Write('>>Enter the filename for saving out your list: ');
Readln(WorkName);
Assign(WorkFile,WorkName); { Open the file for write access }
Rewrite(WorkFile);
Current := Root;
WHILE Current <> Nil DO { Traverse and write }
BEGIN
Write(WorkFile,Current^);
Current := Current^.Next
END;
Close(WorkFile)
END;
BEGIN { MAIN }
ClrScr;
GotoXY(28,1); Write('<<Linked List Maker>>');
CheckSpace;
GotoXY(17,8); Write('--------------------------------------------');
Root := Nil; Quit := False;
REPEAT
ClearLines(5,7);
ClearLines(9,24);
GotoXY(1,5);
Write
('>>[L]oad, [A]dd record, [V]iew, [S]ave, [C]lear list, or [Q]uit: ');
Readln(Ch); { Get a command }
CASE Ch OF
'A','a' : AddRecords(Root); { Parse the command & perform it }
'C','c' : ListDispose(Root);
'L','l' : LoadList(Root);
'S','s' : SaveList(Root);
'V','v' : ViewList(Root);
'Q','q' : Quit := True;
END; { CASE }
UNTIL Quit
END.