WalnutWindowInternalImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Willie-Sue, September 29, 1986 1:24:26 pm PDT
Contents: (Internal communication for) Top level Viewer for Walnut
Last edit by:
Willie-Sue on: January 7, 1985 9:22:19 am PST
Donahue, January 2, 1985 3:42:26 pm PST
DIRECTORY
Containers,
Icons USING [IconFlavor],
FS USING [Error, OpenFile, Create, SetKeep, StreamFromOpenFile],
IO,
Labels USING [Set],
Menus,
MessageWindow USING [Append],
Process USING [Detach, Pause, SecondsToTicks],
Rope,
TypeScript USING [Create],
UserProfile USING [Boolean],
ViewerClasses USING [Viewer],
ViewerEvents USING [EventRegistration, UnRegisterEventProc],
ViewerOps,
ViewerIO USING [CreateViewerStreams],
ViewerSpecs,
WalnutOps USING [ServerInfo, ActiveMsgSetName,
AcceptNewMail, GetNewMail,
RecordNewMailInfo, RegisterReporter, Shutdown, StartNewMail, UnregisterReporter],
WalnutNewMail USING [DisableMailRetrieval, EnableMailRetrieval],
WalnutSendOps USING [userRName, RegisterReporter, UnregisterReporter],
WalnutControlInternal USING [
mailNotifyLabel, mustQuitWalnut, WaitCallOutcome, walnutMenu, workingMenu,
ChangeMenu, DoWaitCall],
WalnutDisplayerInternal USING [AddNewMsgsToActive],
WalnutWindowInternal USING [MailState, MsgSetButton,
firstMsgSetButton, selectedMsgSetButtons, msgSetsTViewer,
personalMailDB, newMailIcon, walnut, walnutEventReg, walnutIcon, walnutTS,
GetButton],
WalnutWindow USING [];
WalnutWindowInternalImpl: CEDAR PROGRAM
IMPORTS
Labels, MessageWindow,
FS, IO, Process, Rope, UserProfile,
TypeScript, ViewerEvents, ViewerOps, ViewerIO,
WalnutOps,
WalnutControlInternal,
WalnutNewMail, WalnutSendOps,
WalnutDisplayerInternal, WalnutWindowInternal
EXPORTS WalnutWindowInternal, WalnutWindow =
BEGIN OPEN WalnutControlInternal, WalnutWindowInternal;
Walnut Viewers types and global data
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
wtsOut: IO.STREAMNIL;
* * * * * * * * * * * * exported to WalnutWindowInternal
Report: PUBLIC PROC[msg1, msg2, msg3: ROPENIL] =
{ DoReport[msg1, msg2, msg3, TRUE] };
ReportRope: PUBLIC PROC[msg1, msg2, msg3: ROPENIL] =
{ DoReport[msg1, msg2, msg3, FALSE] };
DoReport: PROC[msg1, msg2, msg3: ROPENIL, doCR: BOOL] = {
IF wtsOut = NIL THEN
{ IF msg1#NIL THEN MessageWindow.Append[msg1];
IF msg2#NIL THEN MessageWindow.Append[msg2];
IF msg3#NIL THEN MessageWindow.Append[msg3];
RETURN
};
IF msg1#NIL THEN wtsOut.PutRope[msg1];
IF msg2#NIL THEN wtsOut.PutRope[msg2];
IF msg3#NIL THEN wtsOut.PutRope[msg3];
IF doCR THEN wtsOut.PutChar['\n];
wtsOut.Flush[];
};
RetrieveNewMail: PUBLIC PROC = {
Rnm: PROC = {
ENABLE UNWIND => { ChangeMenu[walnutMenu, FALSE] };
responses: LIST OF WalnutOps.ServerInfo;
complete: BOOL;
numNew, total: INT ← 0;
msB: MsgSetButton ← GetButton[WalnutOps.ActiveMsgSetName];
ChangeMenu[workingMenu, TRUE];
IF msB.msViewer # NIL THEN
IF msB.msViewer.destroyed THEN msB.msViewer ← NIL;
IF msB.msViewer = NIL THEN {  -- not displayed
[responses, complete] ← WalnutOps.GetNewMail[msB.msgSet.version, NIL];
numNew ← -1;
WalnutOps.AcceptNewMail[msB.msgSet.version];
}
ELSE
[responses, complete, numNew] ← WalnutDisplayerInternal.AddNewMsgsToActive[msB];
IF ~complete THEN {
Report[" There were problems with GetNewMail - some messages not available; try again"];
ChangeMenu[walnutMenu, FALSE];
RETURN
};
FOR rL: LIST OF WalnutOps.ServerInfo ← responses, rL.rest UNTIL rL = NIL DO
total ← total + rL.first.num; ENDLOOP;
IF total = 0 THEN
Report["No messages were on the newMailLog"]
ELSE {
FOR rL: LIST OF WalnutOps.ServerInfo ← responses, rL.rest UNTIL rL = NIL DO
ReportRope[rL.first.server];
IF rL.first.num = 0 THEN
Report[" ... empty"]
ELSE {
IF rL.first.num = 1 THEN Report[" delivered 1 message"]
ELSE Report[IO.PutFR[" delivered %g messages", IO.int[rL.first.num]]];
};
ENDLOOP;
IF (numNew >= 0) AND (total # numNew) THEN {
IF numNew = 0 THEN
Report["\nNo new messages added to database"]
ELSE Report[IO.PutFR["\nOnly %g messages were new", IO.int[numNew]] ];
};
};
SetMailState[noMail];
ChangeMenu[walnutMenu, FALSE];
};
[] ← DoWaitCall[Rnm];
};
EnableNewMail: PUBLIC PROC = {
progress: BOOL = UserProfile.Boolean[key: "Walnut.ReportNewMailProgress", default: FALSE];
progressLog: ROPE =
Rope.Cat["///Users/", WalnutSendOps.userRName, "/WalnutNewMailProgress.log"];
FS.SetKeep[progressLog, 5 ! FS.Error => CONTINUE];
IF newMailProgressStream = NIL THEN
IF progress THEN {
newMailProgressTS ← TypeScript.Create[
info: [name: "NewMail Retrieval", iconic: FALSE, column: right, openHeight: 64],
paint: FALSE];
ViewerOps.TopViewer[viewer: newMailProgressTS, paint: TRUE];
newMailProgressTS.inhibitDestroy ← TRUE;
newMailProgressStream ← ViewerIO.CreateViewerStreams[
 name: NIL, viewer: newMailProgressTS, backingFile: progressLog].out;
}
ELSE {
of: FS.OpenFile = FS.Create[progressLog, TRUE, 2, TRUE, 5];
newMailProgressStream ← FS.StreamFromOpenFile[of, $write];
};
WalnutNewMail.EnableMailRetrieval[
reportProc: ReportProc,
progressProc: ProgressReport,
getMailLog: GetMailLog,
recordMailInfo: RecordNewMailInfo,
notifyWhenMailRetrieved: NotifyWhenMailRetrieved];
IF newMailProgressTS # NIL THEN newMailProgressTS.inhibitDestroy ← FALSE;
};
DisableNewMail: PUBLIC PROC = {
WalnutNewMail.DisableMailRetrieval[];
IF newMailProgressStream # NIL THEN {
IF newMailProgressTS = NIL THEN newMailProgressStream.Close[]
ELSE IF ~newMailProgressTS.destroyed THEN {
newMailProgressStream.Close[];
ViewerOps.DestroyViewer[newMailProgressTS];
};
newMailProgressStream ← NIL;
newMailProgressTS ← NIL;
};
};
tsLogName: ROPE = "///Temp/Walnut/Walnut.TypescriptLog";
OpenTS: PUBLIC PROC[r: ROPENIL, doRegister: BOOLTRUE] = {
FS.SetKeep[tsLogName, 10 ! FS.Error => CONTINUE];  -- if tsLogName doesn't exist
IF wtsOut = NIL THEN
{ wtsOut ← ViewerIO.CreateViewerStreams[NIL, walnutTS, tsLogName].out;
IF r # NIL THEN wtsOut.PutRope[r];
IF doRegister THEN {
WalnutSendOps.RegisterReporter[wtsOut];
WalnutOps.RegisterReporter[wtsOut];
};
};
};
CloseTS: PUBLIC PROC = {
IF wtsOut # NIL THEN wtsOut.Close[];
WalnutSendOps.UnregisterReporter[wtsOut];
WalnutOps.UnregisterReporter[wtsOut];
wtsOut ← NIL;
};
GetTSStream: PUBLIC PROC RETURNS[IO.STREAM] =
{ RETURN[wtsOut] };
CloseDownWalnut: PUBLIC PROC = {
clean up after Walnut
v: Viewer ← walnut;
IF walnut = NIL THEN RETURN;  -- not running
walnut.inhibitDestroy ← TRUE;
DisableNewMail[];
ChangeMenu[workingMenu, FALSE];
selectedMsgSetButtons ← firstMsgSetButton ← NIL;
TakeDownWalnutViewers[];
ReportRope["Closing database and saving log ..."];
WalnutOps.Shutdown[];
IF walnutEventReg # NIL THEN
ViewerEvents.UnRegisterEventProc[walnutEventReg, destroy];
walnutEventReg ← NIL;
walnut ← NIL;  -- don't let others try to use Report
mailNotifyLabel ← NIL;
WalnutSendOps.UnregisterReporter[wtsOut];
WalnutOps.UnregisterReporter[wtsOut];
wtsOut.Close[];
wtsOut ← NIL;
mustQuitWalnut ← NIL;
v.inhibitDestroy ← FALSE;
msgSetsTViewer ← NIL;
ViewerOps.DestroyViewer[v];
};
EnumWalnutViewers: PUBLIC PROC[keepSeparate: BOOL]
RETURNS [msgSetList, msgList: LIST OF Viewer] = {
Enum: ViewerOps.EnumProc = {
IF ViewerOps.FetchProp[v, $WalnutMsgSetName] # NIL THEN
{ msgSetList← CONS[v, msgSetList]; RETURN[TRUE] };
IF ViewerOps.FetchProp[v, $WalnutMsgName] # NIL THEN
{ IF keepSeparate THEN msgList← CONS[v, msgList]
ELSE msgSetList← CONS[v, msgSetList];
RETURN[TRUE]
};
};
ViewerOps.EnumerateViewers[Enum]
};
TakeDownWalnutViewers: PUBLIC PROC = {
msgSetL, msgL: LIST OF Viewer;
[msgSetL, msgL] ← EnumWalnutViewers[TRUE];
FOR vL: LIST OF Viewer ← msgL, vL.rest UNTIL vL=NIL DO
IF ViewerOps.FetchProp[vL.first, $Frozen] = NIL THEN ViewerOps.DestroyViewer[vL.first];
ENDLOOP;
FOR vL: LIST OF Viewer ← msgSetL, vL.rest UNTIL vL=NIL DO
ViewerOps.DestroyViewer[vL.first];
ENDLOOP;
};
* * * * * * * * * * support for new mail
newMailProgressTS: Viewer;
newMailProgressStream: STREAMNIL;
ReportProc: PROC[r: ROPE] = { Report[r] };
ProgressReport: PROC[r: ROPE] = {
IF newMailProgressTS # NIL THEN
IF newMailProgressTS.destroyed THEN {
newMailProgressTS ← NIL;
newMailProgressStream ← NIL;
};
IF newMailProgressStream # NIL THEN {
newMailProgressStream.PutRope[r];
newMailProgressStream.Flush[];
};
};
GetMailLog: PROC RETURNS[strm: STREAM] = {
outcome: WalnutControlInternal.WaitCallOutcome;
Gml: PROC =
{ strm ← WalnutOps.StartNewMail[] };
IF (outcome ← DoWaitCall[Gml]) = ok THEN {
SetMailState[retrieving];
RETURN;
};
IF outcome = notRunning THEN Process.Pause[Process.SecondsToTicks[20]];
outcome ← DoWaitCall[Gml];  -- try again
IF outcome = ok THEN SetMailState[retrieving];
};
RecordNewMailInfo: PROC[logLen: INT, server: ROPE, num: INT]
RETURNS[ok: BOOL] = {
Rnml: PROC = {
ok ← FALSE;
WalnutOps.RecordNewMailInfo[logLen, server, num];
ok ← TRUE;
};
[] ← DoWaitCall[Rnml];
};
NotifyWhenMailRetrieved: PROC[ok: BOOL, someMail: BOOL] = {
IF ~someMail THEN { SetMailState[noMail]; RETURN};
SetMailState[thereIsMail];
IF personalMailDB THEN {
autoNewMail: BOOL ← UserProfile.Boolean[key: "Walnut.AutoNewMail", default: FALSE];
IF autoNewMail THEN
TRUSTED { Process.Detach[FORK RetrieveNewMail[] ] };
};
};
SetMailState: PUBLIC PROC[mailState: MailState] = {
status: ROPE;
icon: Icons.IconFlavor ← walnutIcon;
IF walnut = NIL THEN RETURN;
SELECT mailState FROM
noMail => status ← "There is no new mail at %g";
retrieving => status ← "Mail is being retrieved at %g";
thereIsMail => {
icon ← newMailIcon;
status ← "You have new mail at %g";
};
gvWaiting => status ← "Waiting (15 sec) for initial grapevine response at %g";
noGV => status ← "No mailbox state reported from grapevine at %g";
noServers => status ← "All of the mail servers are down at %g";
gvMail => status ← "Mail on grapevine at %g";
ENDCASE => NULL;
IF walnut.icon # icon THEN {
walnut.icon← icon;
IF walnut.iconic THEN ViewerOps.PaintViewer[walnut, all];
};
Labels.Set[mailNotifyLabel, IO.PutFR[status, IO.time[]] ];
};
END.