home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.update.uu.se
/
ftp.update.uu.se.2014.03.zip
/
ftp.update.uu.se
/
pub
/
rainbow
/
msdos
/
misc
/
messages.lzh
/
MESSAGES.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1984-08-31
|
20KB
|
679 lines
PROGRAM Messages(input,output); { Hold messages for people by name. }
{ Written by Stew Stryker for the DEC Rainbow under CP/M - 7/84 }
{ Made more generic under MSDOS - 7/85 }
{ Functions: Display names of message holders on screen
and optionally on comm port terminal
Add new messages to list and save to file
Print messages + mark deleted in file
Allow user to define title and printout message
Provide menu of above functions }
{$C-} { Set up so ^C not allowed, which helps KEYPRESSED }
CONST
ProgramVersion = '1.0';
MaxNumOfHolders = 1200;
MaxNumOfDeleted = 500;
ProgramTitle = 'Telephone Message System';
BottomTitle = 'Telephone Messages';
DHTH = ^['#3';
DHBH = ^['#4';
DW = ^['#6';
Reverse = ^['[7m';
Bold = ^['[1m';
Norm = ^['[0m';
LenLast = 20;
LenFirst = 20;
LenFrom = 40;
LenName = 40; { Length of full name }
LenPhone = 13;
LenDate = 20;
LenMessage = 60;
Const
GrOn = ^['(0';
GrOff = ^['(B';
Vln = 'x';
Hln = 'q';
Ulc = 'l';
Urc = 'k';
llc = 'm';
lrc = 'j';
{$I FASTVID.INC } { Fast Video used by new data input routines }
TYPE
Message = RECORD
LName : STRING[LenLast];
FName : STRING[LenFirst];
From : STRING[LenFrom];
Phone : STRING[LenPhone];
DateTime : STRING[LenDate];
Message1 : STRING[LenMessage];
Message2 : STRING[LenMessage];
Deleted : BOOLEAN;
END;
Holder = RECORD
LName : STRING[LenLast];
FName : STRING[LenFirst];
RecordNum : INTEGER;
END;
STR80 = String[80];
LString = String[80];
NameString = STRING[LenName];
VAR
MessageFile : FILE OF MESSAGE;
MessageHolder : ARRAY[1..MaxNumOfHolders] OF HOLDER;
DeletedRecNum : ARRAY[1..MaxNumOfDeleted] OF INTEGER;
CommPort, ToggleFormLength : BOOLEAN;
InputChar : CHAR;
NumFileRecs, CurrDisp, Row, Col, NumOfDeleted, FileRecNum,
FormLength, NumOfHolders : INTEGER;
MiscTitle, TopTitle, SysMessage : STR;
NewMessage : MESSAGE;
I : Integer;
HBar : Str;
{$I EXIST.INC } { Function to determine if file exists }
{$I MESSADD.INC } { Data entry screen for adding new messages }
{$I MESSMORE.INC } { Data entry screen for adding more recipients }
{$I STRING.INC } { String manipulation functions }
FUNCTION FnMove(Col,Row : INTEGER) : STR;
VAR
RowText, ColText : STRING[2];
BEGIN
IF Row >= 10 THEN STR(Row:2,RowText)
ELSE STR(Row:1,RowText);
IF Col >= 10 THEN STR(Col:2,ColText)
ELSE STR(Col:1,ColText);
FnMove := ^[ + '[' + RowText + ';' + ColText + 'H';
END; { FnMove }
FUNCTION FindNextHolder(MatchString : NAMESTRING) : INTEGER;
{ Search the list of holders for the record # with a key after
that in the new message }
VAR
HolderString : STRING[41];
Counter : INTEGER;
BEGIN
Counter := 0;
HolderString := ' ';
MatchString := UpperCase(MatchString);
REPEAT
Counter := Counter + 1;
IF Counter <= NumOfHolders THEN
HolderString := UpperCase(TrimR(MessageHolder[Counter].LName) +
TrimR(MessageHolder[Counter].FName));
UNTIL (Counter > NumOfHolders) OR (MatchString <= HolderString);
FindNextHolder := Counter;
END; { FindNextHolder }
PROCEDURE DisplayMessageHolders;
LABEL StopDisplay;
CONST
RegionOn = ^['[3;22r';
RegionOff = ^['[1;24r';
ClrHome = ^['[H'^['[2J';
Flash = ^['[5m';
TopLine = 3;
BottomLine = 22;
VAR
InputChar : CHAR;
HolderName,DummyString : STRING[42];
BEGIN
{ If there are no messages, don't display anything. }
If NumOfHolders = 0
Then Begin
GotoXY(10,24);
NormVideo;
Write(^G,^G,'There are no messages to display.');
LowVideo;
Delay(4000);
Goto StopDisplay;
End; { If there are no messages to display. }
{ Set up scroll region, and display titles, first for screen,
then for comm port, if necessary }
ClrScr;
WRITE(RegionOn);
GOTOXY(1,1);
{ NormVideo; }
WRITE(Reverse,DHTH,PadR(Center(TopTitle,40),40));
GOTOXY(1,2);
WRITE(DHBH,PadR(Center(TopTitle,40),40));
GOTOXY(1,23);
WRITE(DHTH,PadR(Center(BottomTitle,40),40));
GOTOXY(1,24);
WRITE(DHBH,PadR(Center(BottomTitle,40),40),Norm);
NormVideo;
{ Send same to comm port, if necessary }
IF CommPort THEN BEGIN
WRITE(Aux,ClrHome);
WRITE(Aux,RegionOn);
WRITE(Aux,FnMove(1,1));
{ WRITE(Aux,Norm); }
WRITE(Aux,Reverse,DHTH,PadR(Center(TopTitle,40),40));
WRITE(Aux,FnMove(1,2));
WRITE(Aux,DHBH,PadR(Center(TopTitle,40),40));
WRITE(Aux,FnMove(1,23));
WRITE(Aux,DHTH,PadR(Center(BottomTitle,40),40));
WRITE(Aux,FnMove(1,24));
WRITE(Aux,DHBH,PadR(Center(BottomTitle,40),40));
WRITE(Aux,Bold);
END; { Sending titles to the comm port }
{ You've just turned off reverse video, and turned bold on }
IF (CurrDisp < 1) Or (CurrDisp > NumOfHolders)
THEN CurrDisp := 1;
{ Until a key is pressed, Display the names of the message holders }
REPEAT
WITH MessageHolder[CurrDisp] DO
HolderName := LName + ', ' + FName;
GOTOXY(1,BottomLine);
IF CommPort THEN WRITE(Aux,FnMove(1,BottomLine));
WRITELN(DHTH,HolderName);
IF CommPort THEN WRITELN(Aux,DHTH,HolderName);
WRITELN(DHBH,HolderName);
IF CommPort THEN WRITELN(Aux,DHBH,HolderName);
CurrDisp := (CurrDisp + 1) MOD (NumOfHolders + 1);
IF CurrDisp = 0 THEN CurrDisp := 1;
UNTIL Keypressed;
StopDisplay:
WRITE(RegionOff,Norm);
{ Set up comm port with "Updating" message, if necessary }
IF CommPort THEN BEGIN
WRITE(Aux,RegionOff,Flash);
WRITE(Aux,FnMove(1,23));
WRITE(Aux,DHTH,Center('Updating Telephone Messages',40));
WRITE(Aux,FnMove(1,24));
WRITE(Aux,DHBH,Center('Updating Telephone Messages',40));
WRITE(Aux,FnMove(1,24),' ',^H);
END; { Stopping display to comm port }
ClrScr;
END; { DisplayMessageHolders }
PROCEDURE AddHolder;
{ Add new name and record number to Message Holder array }
VAR
Counter, PositionToInsertHolder : INTEGER;
BEGIN
PositionToInsertHolder := FindNextHolder(NewMessage.LName +
NewMessage.FName);
NumOfHolders := NumOfHolders + 1;
{ Move all subsequent holders down list }
FOR Counter := NumOfHolders DOWNTO PositionToInsertHolder + 1 DO
MessageHolder[Counter] := MessageHolder[Counter - 1];
{ Add new Holder to list }
WITH MessageHolder[PositionToInsertHolder] DO BEGIN
LName := NewMessage.LName;
FName := NewMessage.FName;
RecordNum := FileRecNum;
END;
END; { AddHolder }
Procedure SetSystemTitles;
{ Set and save system titles }
Var
SaveMessage : Char;
TempLength : Integer;
TitleFile : Text;
TempToggle, TempTitle, TempMessage : STR80;
{$I MESSSET.INC } { Data entry screen for entering system titles }
Begin
{ Get titles and ask if they want to save them }
SaveMessage := ' ';
If (FormLength < 33) Or (FormLength > 66)
Then FormLength := 33;
TempLength := FormLength;
Repeat
ClrScr;
MessSet; { Get input for new message titles }
Until (TempLength > 32) And (TempLength < 67);
GotoXY(1,24);
MiscTitle := 'Do you want to save these titles to the disk? (Y/N)';
Write(TrimR(Center(MiscTitle,80)));
Read(Kbd,SaveMessage);
If TrimR(TempTitle) > '' { Only save these if }
Then TopTitle := TempTitle;
If TrimR(TempMessage) > '' { they've been changed }
Then SysMessage := TempMessage;
FormLength := TempLength;
If UpCase(SaveMessage) = 'Y'
Then
Begin
Writeln;
Writeln('Saving titles.');
{ Save to file }
Assign(TitleFile,'MESSAGES.MAS');
Rewrite(TitleFile);
Writeln(TitleFile,TopTitle);
Writeln(TitleFile,SysMessage);
Writeln(TitleFile,FormLength);
Close(TitleFile);
End; { If they wanted to save the titles }
End; { Procedure SetSystemTitles }
PROCEDURE InitializeProgram;
{ Set up files and things }
VAR
OK : BOOLEAN;
TitleFile : Text;
BEGIN
{ Initialize variables }
NumFileRecs := 0;
NumOfDeleted := 0;
NumOfHolders := 0;
TopTitle := ' '; { Initialize these to blanks }
SysMessage := ' ';
{ Read in system's title and message }
If Exist('MESSAGES.MAS') Then
Begin
Assign(TitleFile,'MESSAGES.MAS');
Reset(TitleFile);
Readln(TitleFile,TopTitle);
Readln(TitleFile,SysMessage);
Readln(TitleFile,FormLength);
Close(TitleFile);
End
Else SetSystemTitles; { Get user's title inputs }
{ Open message data file, or create if necessary }
Writeln;
Writeln('Checking for messages...');
ASSIGN(MessageFile,'MESSAGES.DAT');
{$I-} RESET(MessageFile) {$I+};
OK := (IOresult = 0);
IF NOT OK
THEN REWRITE(MessageFile) { Create a new file }
Else Write('Reading messages');
{ If OK, you should read the file of old messages, and set up
your arrays and counters again. }
IF OK THEN
WHILE NOT EOF(MessageFile) DO BEGIN
READ(MessageFile,NewMessage);
IF NewMessage.Deleted = TRUE THEN
BEGIN
NumOfDeleted := NumOfDeleted + 1;
DeletedRecNum[NumOfDeleted] := NumFileRecs;
END { If message has been deleted }
ELSE
BEGIN
FileRecNum := NumFileRecs;
AddHolder; { Add this name to sorted holder list }
WRITE('.');
END;
NumFileRecs := NumFileRecs + 1;
END; { While there are messages to be read }
NumOfHolders := NumFileRecs - NumOfDeleted;
{ Check if they have a terminal on the comm port }
ClrScr;
NormVideo;
{ Draw program title }
Hbar := '';
For I := 1 to 26 Do Hbar := Hbar + Hln;
GOTOXY(6,1);
Write(GrOn,DW,Ulc);
Write(Hbar,Urc);
GOTOXY(6,2);
Write(DHTH,Vln,GrOff,' ',ProgramTitle,' ',GrOn,Vln);
GOTOXY(6,3);
Write(DHBH,Vln,GrOff,' ',ProgramTitle,' ',GrOn,Vln);
GOTOXY(6,4);
Write(DW,Llc,HBar,Lrc,GrOff);
LowVideo;
GOTOXY(1,5);
Writeln(Center('Version '+ProgramVersion+' by Stew Stryker',80));
GOTOXY(1,12);
LowVideo;
WRITELN(Center('Do you have a terminal',80));
WRITE(Center('attached to the communications port? (Y/N) ',
80));
NormVideo;
Repeat
READ(Kbd,InputChar);
Until InputChar In ['Y','y','N','n'];
IF UpCase(InputChar) = 'Y' THEN CommPort := TRUE
ELSE CommPort := FALSE;
END; { Initialize Program }
FUNCTION FindThisHolder(MatchString : NAMESTRING) : INTEGER;
{ Search the list of holders for the record # with a key after
that in the new message }
VAR
HolderString : STRING[41];
Counter : INTEGER;
BEGIN
Counter := 0;
HolderString := ' ';
MatchString := UpperCase(MatchString);
REPEAT
Counter := Counter + 1;
IF Counter <= NumOfHolders THEN
HolderString := UpperCase(MessageHolder[Counter].LName +
MessageHolder[Counter].FName);
UNTIL (Counter > NumOfHolders) OR (MatchString >= HolderString);
FindThisHolder := Counter;
END; { FindThisHolder }
PROCEDURE SaveMsg;
{ Save the new message to the holder array, and to the file }
BEGIN
NewMessage.Deleted := False;
{ Save message to file }
IF NumOfDeleted > 0 THEN
BEGIN
FileRecNum := DeletedRecNum[NumOfDeleted];
NumOfDeleted := NumOfDeleted - 1;
END
ELSE BEGIN
FileRecNum := NumFileRecs;
NumFileRecs := NumFileRecs + 1;
END;
{ Save new message to disk, and ensure it was written }
SEEK(MessageFile,FileRecNum);
WRITE(MessageFile,NewMessage);
FLUSH(MessageFile);
AddHolder;
WRITE('Saved.');
END; { SaveMsg }
PROCEDURE CarbonCopy;
{ Send a copy of a message to another recipient }
VAR
SendThisCopy : CHAR;
BEGIN
MessMore; { Get name of next recipient }
GOTOXY(1,22);
CLREOL;
MiscTitle := 'Do you want to send this copy? (Y/N) ';
Write(TrimR(Center(MiscTitle,80)));
Read(Kbd,SendThisCopy);
GOTOXY(1,22);
ClrEol;
GOTOXY(38,22);
If UpCase(SendThisCopy) = 'Y' Then
SaveMsg;
End; { Procedure CarbonCopy }
PROCEDURE AddNewMessages;
{ Keep adding new messages until they say no to another }
VAR
AnotherMessage, AnotherCopy, SaveThisMessage : CHAR;
BEGIN
AnotherMessage := 'Y';
WHILE AnotherMessage = 'Y' DO BEGIN
MessAdd; { Get the input from the included routine }
GOTOXY(1,22);
{ Check to see if they want to save this message }
SaveThisMessage := 'N';
MiscTitle := 'Do you want to save this message? (Y/N) ';
WRITE(TrimR(Center(MiscTitle,80)));
READ(Kbd,SaveThisMessage);
GOTOXY(1,22);
ClrEol;
GOTOXY(38,22);
IF UpCase(SaveThisMessage) = 'Y' THEN
SaveMsg;
{ Allow user to send carbon copy to another person }
AnotherCopy := 'Y';
While UpCase(AnotherCopy) = 'Y' Do Begin
GOTOXY(1,23);
CLREOL;
MiscTitle :=
'Do you wish to send another copy of this message? (Y/N) ';
Write(TrimR(Center(MiscTitle,80)));
Read(Kbd,AnotherCopy);
GOTOXY(1,23);
ClrEol;
If UpCase(AnotherCopy) = 'Y'
Then CarbonCopy;
End; { While they want to send another copy }
{ Allow user to add another message }
GOTOXY(1,24);
CLREOL;
MiscTitle := 'Do you want to add another message? (Y/N) ';
WRITE(TrimR(Center(MiscTitle,80)));
READ(Kbd,AnotherMessage);
AnotherMessage := UpCase(AnotherMessage);
END; { While AnotherMessage }
END; { AddNewMessages }
PROCEDURE DeleteMessage(HolderNum : INTEGER);
{ Add record to deleted list, mark message in file deleted,
Remove from holder list }
VAR
FileRecNum, Counter : INTEGER;
BEGIN
{ Add to deleted list }
FileRecNum := MessageHolder[HolderNum].RecordNum;
NumOfDeleted := NumOfDeleted + 1;
DeletedRecNum[NumOfDeleted] := FileRecNum;
{ Mark file message as deleted }
SEEK(MessageFile, FileRecNum);
READ(MessageFile, NewMessage);
NewMessage.Deleted := TRUE;
SEEK(MessageFile, FileRecNum);
WRITE(MessageFile, NewMessage);
FLUSH(MessageFile);
{ Remove holder from holder list }
NumOfHolders := NumOfHolders - 1;
FOR Counter := HolderNum TO NumOfHolders DO
MessageHolder[Counter] := MessageHolder[Counter + 1];
END; { DeleteMessage }
PROCEDURE PrintMessage(HolderNum : INTEGER);
{ Print message on the printer }
CONST
FormOffset = 21;
Margin = ' ';
VAR
TabStop, Counter : INTEGER;
BEGIN
Writeln(Lst,Bold,TrimR(Center('Telephone Message System',80)),Norm);
Writeln(Lst,TrimR(Center('(Provided by RONNIE Support Group)',80)));
Writeln(Lst);
WRITELN(Lst,Bold,TrimR(Center(TopTitle,80)),Norm);
WRITELN(Lst);
WRITELN(Lst);
WRITELN(Lst);
FileRecNum := MessageHolder[HolderNum].RecordNum;
SEEK(MessageFile,FileRecNum);
READ(MessageFile,NewMessage);
WITH NewMessage DO BEGIN
WRITELN(Lst,Margin,PadR('TO: '+LName+', '+FName,50),
'D/T: ',DateTime);
WRITELN(Lst);
WRITELN(Lst,Margin,PadR('FROM: '+From,50),
'TEL: ', Phone);
WRITELN(Lst);
WRITELN(Lst);
Writeln(Lst,Margin,'------------------------------------',
' Message ', '------------------------------------');
WRITELN(Lst,Margin,Message1);
WRITELN(Lst,Margin,' ',Message2);
END;
{ Insert spaces to fill out form }
FOR Counter := 1 to (FormLength - FormOffset) DO WRITELN(Lst);
{ Print footer }
WRITELN(Lst,TrimR(Center('DIGITAL EQUIPMENT CORPORATION',80)));
WRITELN(Lst,TrimR(Center(SysMessage,80)));
WRITELN(Lst);
WRITELN(Lst);
WRITELN(Lst);
WRITELN(Lst);
END; { Print Messages }
PROCEDURE FindMessages;
{ Let the user search the list for a message holder }
VAR
Found, SearchAgain : CHAR;
SearchFirst : STRING[LenFirst];
SearchLast : STRING[LenLast];
SearchNum : INTEGER;
{$I MESSSEAR.INC } { Include file to enter search name }
BEGIN
SearchAgain := 'Y';
WHILE SearchAgain = 'Y' DO BEGIN
ClrScr;
MessSear; {Get input of the name to search for from Include }
SearchNum := FindNextHolder(TrimR(SearchLast) +
TrimR(SearchFirst));
GOTOXY(20,20);
IF (SearchNum < 1) OR (SearchNum > NumOfHolders) THEN
WRITELN('I can''t find anyone by that name!')
ELSE BEGIN
WRITE('Is ',MessageHolder[SearchNum].FName,
' ',MessageHolder[SearchNum].LName,
' the one you want? (Y/N) ');
READ(Kbd,Found);
IF UpCase(Found) = 'Y' THEN
BEGIN
Writeln;
Writeln('Printing message...');
PrintMessage(SearchNum);
Writeln('Deleting message...');
DeleteMessage(SearchNum);
END; { This is the right one }
END; { There was some sort of match }
GOTOXY(20,24);
WRITE('Do you want to search again? (Y/N) ');
READ(Kbd,SearchAgain);
SearchAgain := UpCase(SearchAgain);
END; { Search until they don't want to search again }
END; { FindMessages }
PROCEDURE Menu;
BEGIN
InputChar := ' ';
ClrScr;
NormVideo;
{ Draw program title }
Hbar := '';
For I := 1 to 26 Do Hbar := Hbar + Hln;
GOTOXY(6,1);
Write(GrOn,DW,Ulc);
Write(Hbar,Urc);
GOTOXY(6,2);
Write(DHTH,Vln,GrOff,' ',ProgramTitle,' ',GrOn,Vln);
GOTOXY(6,3);
Write(DHBH,Vln,GrOff,' ',ProgramTitle,' ',GrOn,Vln);
GOTOXY(6,4);
Write(DW,Llc,HBar,Lrc,GrOff);
LowVideo;
GOTOXY(20 - (Length(TopTitle) Div 2),5);
WRITE(DW,Reverse,TrimL(TrimR(Center(TopTitle,40))),Norm);
GOTOXY(14,8);
WRITE(DW);
NormVideo;
WRITE('A');
LowVideo;
WRITE('dd New Messages');
GOTOXY(14,10);
WRITE(DW);
NormVideo;
WRITE('D');
LowVideo;
WRITE('isplay Messages');
GOTOXY(14,12);
WRITE(DW);
NormVideo;
Write('C');
LowVideo;
Write('hange System Titles');
GOTOXY(14,14);
WRITE(DW);
NormVideo;
WRITE('F');
LowVideo;
WRITE('ind Messages');
GOTOXY(14,16);
WRITE(DW);
Normvideo;
WRITE('Q');
LowVideo;
WRITE('uit program');
GOTOXY(50,24);
WRITE('There are ',NumOfHolders,' messages.');
GOTOXY(1,21);
WRITE(DW);
NormVideo;
WRITE('PLEASE ENTER CHOICE (A,D,C,F,Q): ');
LowVideo;
InputChar := ' ';
WHILE NOT (InputChar IN ['A','D','C','F','Q']) DO
BEGIN
GOTOXY(33,21);
Read(Kbd,InputChar);
InputChar := UpCase(InputChar);
END; { Getting input until it is one of the choices }
END; { Menu }
BEGIN { Main program }
InitializeProgram;
REPEAT
Menu;
CASE InputChar OF
'A' : AddNewMessages;
'D' : DisplayMessageHolders;
'C' : SetSystemTitles;
'F' : FindMessages;
END; { CASE statement }
UNTIL InputChar = 'Q';
CLOSE(MessageFile);
END.