-- LaurelTTYInterface.mesa
-- Edited by Brotz, June 24, 1982 3:16 PM
-- Edited by Taft, May 8, 1983 2:04 PM


DIRECTORY
Ascii,
ccD: FROM "ChollaCmdDefs",
dsD: FROM "DisplayDefs",
Editor,
inD: FROM "InteractorDefs",
intCommon,
LaurelTTYDefs,
opD: FROM "OperationsDefs",
String,
vmD: FROM "VirtualMgrDefs";

LaurelTTYInterface: PROGRAM
IMPORTS ccD, dsD, Editor, inD, intC: intCommon, LaurelTTYDefs, String, vmD
EXPORTS LaurelTTYDefs =

BEGIN


TTYInterface: PUBLIC PROCEDURE [h: LaurelTTYDefs.Handle] =
BEGIN OPEN h;
char: CHARACTER;
DO
WriteLine[""L]; WriteChar[’#]; SendNow[];
char ← ReadChar[];
SELECT char FROM
’? => BEGIN
WriteLine["Commands are:"L];
WriteLine["A(nswer <message-number>, D(elete), E(ditor), (Mail) F(ile) <name>,"L];
WriteLine["H(eaders) <list>, I(n-box status), (New) M(ail), N(ext message),"L];
WriteLine["Q(uit), S(end message in editor), T(ype message) <list>, U(ndelete),"L];
WriteLine["? (help message), . (current message is), * (last message is)"L];
WriteLine[""L];
WriteLine["<list> := <item> | <item> , <list>"L];
WriteLine["<item> := <number> | <range>"L];
WriteLine["<range> := <number> : <number>"L];
END;
’A, ’a =>
BEGIN
WriteString["Answer "L];
WriteString["Not yet implemented."L];
SendNow[];
END;
’D, ’d => {WriteString["Delete "L]; SendNow[]; DoMessageList[h, DeleteMessage]};
’E, ’e => {WriteString["Editor"L]; LaurelTTYDefs.TTYEditor[h]};
’F, ’f =>
BEGIN
text: STRING ← intC.mailFileBracketsHouse.text;
dm: inD.MessageTextNbrPtr = intC.dmTextNbr;
tnp: inD.TOCTextNbrPtr = intC.tocTextNbr;
key: CARDINAL ← 0;
WriteString["Mail file {"L]; SendNow[];
[] ← ReadString[text]; WriteLine["}"L]; SendNow[];
inD.BracketsHouseRefresher[intC.mailFileBracketsHouse];
dsD.ClearRectangle[inD.leftMargin, inD.rightMargin, tnp.topY, tnp.bottomY];
dsD.ClearRectangle[inD.leftMargin, inD.rightMargin, dm.topY, dm.bottomY];
IF tnp.toc # NIL AND dm.haveMessage THEN
BEGIN
key ← vmD.WaitForLock[tnp.toc];
vmD.FlushDisplayMessage[vmD.DisplayMessage[dm.message], key];
vmD.UnlockTOC[tnp.toc, key];
END;
dm.haveMessage ← FALSE;
[tnp.toc, key] ← ccD.GetTOCForFile[IF text.length = 0 THEN NIL ELSE text, laurel];
IF (tnp.haveToc ← tnp.toc # NIL) THEN
BEGIN
inD.TOCTextPainter[tnp, key];
vmD.UnlockTOC[tnp.toc, key];
WriteString[text]; WriteString[" has "L];
WriteDecimal[intC.tocTextNbr.toc.indexFF - 1];
WriteLine[" messages."L];
END
ELSE BEGIN
inD.UpdateTOCThumbLine[tnp, key];
WriteLine["Failed."L];
END;
END;
’H, ’h => {WriteString["Headers "L]; SendNow[]; DoMessageList[h, TypeHeader]};
’I, ’i => {WriteString["In-box status: "L]; WriteLine[intC.newMessagesHouse.text]};
’M, ’m =>
BEGIN
oldFF: vmD.TOCIndex ← intC.tocTextNbr.toc.indexFF;
WriteLine["New mail"L]; SendNow[];
inD.GetNewMailCommand[NIL, TRUE];
WriteDecimal[intC.tocTextNbr.toc.indexFF - oldFF];
WriteString[" messages retrieved. Last message is number "L];
WriteDecimal[intC.tocTextNbr.toc.indexFF - 1];
END;
’N, ’n =>
IF currentIndex + 1 < intC.tocTextNbr.toc.indexFF THEN
BEGIN
WriteLine["Next"L]; SendNow[];
currentIndex ← currentIndex + 1;
TypeMessage[h];
IF DelTyped[] THEN {Flush[]; WriteLine[" XXX"L]};
END
ELSE WriteLine["No further messages."L];
’Q, ’q => {WriteLine["Quit"L]; WriteLine["Closing connection"L]; SendNow[]; EXIT};
’S, ’s =>
BEGIN
WriteLine["Send"L];
SendNow[];
IF inD.SendOperation[LaurelTTYDefs.buffer, @intC.user, Editor.FormatMessage] = ok
THEN WriteString["Delivered"L] ELSE WriteString["Not delivered"L];
SendNow[];
END;
’T, ’t => {WriteString["Type "L]; SendNow[]; DoMessageList[h, TypeMessage]};
’U, ’u => {WriteString["Undelete "L]; SendNow[]; DoMessageList[h, UndeleteMessage]};
’. => {WriteString["Current message is "]; WriteDecimal[currentIndex]};
’* =>
BEGIN
WriteString[" Mail file has "L];
WriteDecimal[intC.tocTextNbr.toc.indexFF - 1];
WriteLine[" messages."L];
END;
ENDCASE => {WriteChar[char]; WriteLine["is an unrecognized command."L]};
SendNow[];
ENDLOOP;
END; -- of TTYInterface --


currentIndex: vmD.TOCIndex ← 0;
list: STRING ← [80];


DoMessageList: PROCEDURE
[h: LaurelTTYDefs.Handle, doOneMessage: PROCEDURE [LaurelTTYDefs.Handle]] =
BEGIN
state: {low, high, doneHigh, doneLow} ← low;
num: STRING ← [6];
lowIndex, highIndex: vmD.TOCIndex ← 0;

DoEnd: PROCEDURE RETURNS [BOOLEAN] =
BEGIN
SELECT state FROM
high => highIndex ← String.StringToDecimal
[num ! String.InvalidNumber => GO TO Bad];
low => highIndex ← lowIndex ← String.StringToDecimal
[num ! String.InvalidNumber => GO TO Bad];
doneLow => highIndex ← lowIndex;
ENDCASE;
num.length ← 0;
state ← low;
FOR index: vmD.TOCIndex IN [lowIndex .. highIndex] DO
IF index ~IN [1 .. intC.tocTextNbr.toc.indexFF) THEN
{h.WriteLine["Out of bounds message number"L]; RETURN[FALSE]};
currentIndex ← index;
doOneMessage[h];
IF h.DelTyped[] THEN {h.WriteString[" XXX"L]; h.Flush[]; RETURN[FALSE]};
ENDLOOP;
RETURN[TRUE];
EXITS
Bad => {h.WriteLine["Illegal number in message list."L]; RETURN[FALSE]};
END; -- of DoEnd --

[] ← h.ReadString[list];
h.WriteLine[""L];
FOR i: CARDINAL IN [0 .. list.length) DO
SELECT list[i] FROM
IN [’0 .. ’9] =>
IF (state = low OR state = high) AND num.length < num.maxlength THEN
{num[num.length] ← list[i]; num.length ← num.length + 1}
ELSE GO TO Illegal;
’: =>
BEGIN
SELECT state FROM
low => lowIndex ← String.StringToDecimal
[num ! String.InvalidNumber => GO TO Illegal];
high, doneHigh => GO TO Illegal;
ENDCASE;
num.length ← 0;
state ← high;
END;
’, => IF ~DoEnd[] THEN RETURN;
’* =>
SELECT state FROM
high => {highIndex ← intC.tocTextNbr.toc.indexFF - 1; state ← doneHigh};
low => {lowIndex ← intC.tocTextNbr.toc.indexFF - 1; state ← doneLow};
ENDCASE => GO TO Illegal;
ENDCASE => GO TO Illegal;
REPEAT
FINISHED => IF ~DoEnd[] THEN RETURN;
ENDLOOP;
EXITS
Illegal => h.WriteLine["Illegal number in message list."L];
END; -- of DoMessageList --


TypeMessage: PROCEDURE [h: LaurelTTYDefs.Handle] =
BEGIN
OPEN h;
toc: vmD.TOCHandle ← intC.tocTextNbr.toc;
dm: vmD.DisplayMessagePtr ← vmD.AllocateDisplayMessageObject[];
key: CARDINAL ← vmD.WaitForLock[toc];
vmD.LoadDisplayMessage[toc, key, currentIndex, dm];
WriteChar[’[]; WriteDecimal[vmD.GetMessageSize[dm]]; WriteLine[" characters]"];
FOR i: vmD.CharIndex ← 0, i + 1 UNTIL i = vmD.GetMessageSize[dm] DO
WriteChar[vmD.GetMessageChar[dm, i]];
IF DelTyped[] THEN EXIT;
ENDLOOP;
vmD.FlushDisplayMessage[dm, key];
vmD.UnlockTOC[toc, key];
vmD.FreeVirtualMessageObject[dm];
END; -- of TypeMessage --


TypeHeader: PROCEDURE [h: LaurelTTYDefs.Handle] =
BEGIN
OPEN h;
toc: vmD.TOCHandle ← intC.tocTextNbr.toc;
key: CARDINAL ← vmD.WaitForLock[toc];
tocString: STRING ← [opD.maxTOCStringLength];
fp: vmD.TOCFixedPart;
vmD.GetTOCFixedPart[toc, key, currentIndex, @fp];
vmD.GetTOCString[toc, key, currentIndex, tocString];
vmD.UnlockTOC[toc, key];
WriteChar[IF fp.seen THEN fp.mark ELSE ’?];
WriteChar[IF fp.deleted THEN ’X ELSE Ascii.SP];
WriteDecimal[currentIndex];
WriteChar[Ascii.TAB];
FOR i: CARDINAL IN [0 .. tocString.length) DO
WriteChar[IF tocString[i] = opD.substringSeparator THEN Ascii.TAB ELSE tocString[i]];
ENDLOOP;
WriteLine[""L];
SendNow[];
END; -- of TypeHeader --


DeleteMessage: PROCEDURE [h: LaurelTTYDefs.Handle] =
BEGIN
OPEN h;
toc: vmD.TOCHandle ← intC.tocTextNbr.toc;
key: CARDINAL ← vmD.WaitForLock[toc];
fp: vmD.TOCFixedPart;
vmD.GetTOCFixedPart[toc, key, currentIndex, @fp];
fp.deleted ← TRUE;
vmD.PutTOCFixedPart[toc, key, currentIndex, @fp];
vmD.UnlockTOC[toc, key];
END; -- of DeleteMessage --


UndeleteMessage: PROCEDURE [h: LaurelTTYDefs.Handle] =
BEGIN
OPEN h;
toc: vmD.TOCHandle ← intC.tocTextNbr.toc;
key: CARDINAL ← vmD.WaitForLock[toc];
fp: vmD.TOCFixedPart;
vmD.GetTOCFixedPart[toc, key, currentIndex, @fp];
fp.deleted ← FALSE;
vmD.PutTOCFixedPart[toc, key, currentIndex, @fp];
vmD.UnlockTOC[toc, key];
END; -- of UndeleteMessage --


END. -- of LaurelTTYInterface --