WalnutWindowInternalImpl.mesa
Copyright Ó 1985, 1989, 1992 by Xerox Corporation. All rights reserved.
Willie-Sue, November 3, 1989 11:15:02 am PST
Jack Kent April 1, 1987 2:54:36 pm PST
Doug Terry, October 28, 1990 11:25 am PST
Willie-s, April 27, 1992 7:49 pm PDT
DIRECTORY
<<Atom USING [GetPName],>>
BasicTime USING [Now],
Containers,
Icons USING [IconFlavor],
FS USING [Error, OpenFile, Create, SetKeep, StreamFromOpenFile],
IO,
Labels USING [Set],
MailUtils USING [Credentials, GetUserCredentials],
Menus,
MessageWindow USING [Append],
Process USING [Detach, Pause, SecondsToTicks],
Rope,
SendMailOps USING [RegisterReporter, <<simpleNameListWithoutSpaces,>> UnregisterReporter],
TypeScript USING [Create],
UserProfile USING [Boolean],
ViewerClasses USING [Viewer],
ViewerOps,
ViewerIO USING [CreateViewerStreams],
ViewerSpecs,
WalnutDefs USING [CheckReportProc, Error],
WalnutOps USING [AcceptNewMail, ActiveName, GetNewMail, RecordNewMailInfo, RegisterReporter, ServerInfo, StartNewMail, UnregisterReporter, WalnutOpsHandle],
WalnutNewMail USING [DisableMailRetrieval, EnableMailRetrieval],
WalnutInternal USING [AddNewMsgsToActive, ChangeMenu, CloseDownWalnut, DoWaitCall, FixUpWalnutViewers, GetButton, MailState, QDisplayMsg, QDisplayMsgSet, ShowMsgSetButtons, WaitCallOutcome, workingMenu],
WalnutWindowPrivate USING [IconState, MsgAndHandle, MsgSetButton, MsgSetInfo, WalnutHandle, WalnutHandleRec],
WalnutWindow USING [GetHandleForMail, OutCome];
WalnutWindowInternalImpl:
CEDAR
PROGRAM
IMPORTS
<<Atom,>> BasicTime, Labels, MailUtils, MessageWindow,
FS, IO, Process, <<Rope,>> SendMailOps, UserProfile,
TypeScript, ViewerOps, ViewerIO,
WalnutDefs, WalnutOps,
WalnutNewMail,
WalnutInternal, WalnutWindow
EXPORTS WalnutInternal, WalnutWindow =
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle;
WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec;
MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton;
MsgSetInfo: TYPE = WalnutWindowPrivate.MsgSetInfo;
MsgAndHandle: TYPE = WalnutWindowPrivate.MsgAndHandle;
crTimeToFlushCount: CARDINAL ¬ 3;
timeToFlushCount: CARDINAL ¬ 10;
ReportFormat:
PUBLIC
PROC[wH: WalnutHandle, format:
ROPE ¬
NIL, v1, v2, v3, v4, v5:
IO.Value ¬ [null[]] ] =
{ IF wH.wtsOut # NIL THEN wH.wtsOut.PutFL[format, LIST[v1, v2, v3, v4, v5]] };
Report:
PUBLIC
PROC[wH: WalnutHandle, msg1, msg2, msg3:
ROPE ¬
NIL] = {
ReportRope[wH, msg1, msg2, msg3];
IF wH.wtsOut = NIL THEN RETURN;
wH.wtsOut.PutChar['\n];
IF (wH.crCount ¬ wH.crCount + 1) > crTimeToFlushCount
THEN {
wH.wtsOut.Flush[];
wH.reportCount ¬ wH.crCount ¬ 0;
};
IF (wH.reportCount ¬ wH.reportCount + 1) > timeToFlushCount
THEN {
wH.wtsOut.Flush[];
wH.reportCount ¬ wH.crCount ¬ 0;
};
};
ReportRope:
PUBLIC
PROC[wH: WalnutHandle, msg1, msg2, msg3:
ROPE ¬
NIL] = {
IF wH.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 wH.wtsOut.PutRope[msg1];
IF msg2#NIL THEN wH.wtsOut.PutRope[msg2];
IF msg3#NIL THEN wH.wtsOut.PutRope[msg3];
};
DisplayMsg:
PUBLIC
PROC[wH: WalnutHandle, msg:
ROPE, oldV: Viewer, shift, paint:
BOOL]
RETURNS[v: Viewer] = {
Dm:
PROC = {
-- don't open if iconic
v ¬ QDisplayMsg[wH: wH, msg: msg, oldV: oldV, shift: shift, openIfIconic: FALSE, paint: paint]
};
[] ¬ DoWaitCall[wH, Dm];
};
DisplayMsgSet:
PUBLIC PROC[wH: WalnutHandle, msgSet:
ROPE, shift, repaint:
BOOL]
RETURNS[v: Viewer] = {
Dms:
PROC = {
v ¬ QDisplayMsgSet[wH, GetButton[wH, msgSet], NIL, shift, repaint];
};
[] ¬ DoWaitCall[wH, Dms];
};
CurrentVersion:
PUBLIC
PROC[wH: WalnutHandle, msName:
ROPE]
RETURNS[version:
INT ¬ 0] = {
Dms: PROC = { version ¬ GetButton[wH, msName].msgSet.version };
[] ¬ DoWaitCall[wH, Dms]
};
QueueCall:
PUBLIC
PROC[
wH: WalnutHandle, proc: PROC[wH: WalnutHandle] RETURNS[doReset: BOOL]]
RETURNS[outCome: WalnutWindow.OutCome] = {
Qc:
PROC = {
IF ~proc[wH] THEN RETURN;
ShowMsgSetButtons[wH];
FixUpWalnutViewers[wH];
};
outCome ¬ DoWaitCall[wH, Qc];
};
Shutdown:
PUBLIC
PROC[wH: WalnutHandle] = {
Sd: PROC = { [] ¬ CloseDownWalnut[wH] };
[] ¬ DoWaitCall[wH, Sd];
};
GetNewMail:
PUBLIC
PROC[wH: WalnutHandle] = {
Rnm:
PROC = {
ENABLE UNWIND => { ChangeMenu[wH, wH.walnutMenu, FALSE] };
responses: LIST OF WalnutOps.ServerInfo;
complete: BOOL;
numNew, total: INT ¬ 0;
msB: MsgSetButton ¬ GetButton[wH, WalnutOps.ActiveName];
ChangeMenu[wH, 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[wH.opsH, msB.msgSet.version, NIL];
numNew ¬ -1;
WalnutOps.AcceptNewMail[wH.opsH, msB.msgSet.version];
}
ELSE
[responses, complete, numNew] ¬ AddNewMsgsToActive[msB];
IF ~complete
THEN {
Report[wH, " There were problems with GetNewMail - some messages not available; try again"];
ChangeMenu[wH, wH.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[wH, "No messages were on the newMailLog"]
ELSE {
FOR rL:
LIST
OF WalnutOps.ServerInfo ¬ responses, rL.rest
UNTIL rL =
NIL
DO
ReportRope[wH, rL.first.server];
IF rL.first.num = 0
THEN
Report[wH, " ... empty"]
ELSE {
IF rL.first.num = 1
THEN Report[wH, " delivered 1 message"]
ELSE ReportFormat[wH, " delivered %g messages\n", [integer[rL.first.num]] ];
};
ENDLOOP;
IF (numNew >= 0)
AND (total # numNew)
THEN {
IF numNew = 0
THEN
Report[wH, "\nNo new messages added to database"]
ELSE ReportFormat[wH, "\nOnly %g messages were new", [integer[numNew]] ];
};
};
-- XXX Don't put the flag down if the active msg set is iconic
IF msB.msViewer #
NIL
THEN
IF ( NOT msB.msViewer.iconic ) OR ( NOT UserProfile.Boolean[key: "Walnut.AutoNewMail", default: FALSE] ) THEN
IF wH.personalMailDB THEN SetMailState[wH, noMail];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Rnm];
};
EnableNewMail:
PUBLIC
PROC[wH: WalnutHandle] = {
gvMail: BOOL ~ UserProfile.Boolean["Walnut.gvMail", TRUE];
xnsMail: BOOL ~ UserProfile.Boolean["Walnut.xnsMail", TRUE];
progress: BOOL = UserProfile.Boolean[key: "Walnut.ReportNewMailProgress", default: FALSE];
progressLog:
ROPE = "/tmp/WalnutNewMailProgress.log";
Rope.Cat["/tilde/", SendMailOps.simpleNameListWithoutSpaces.first, "/WalnutNewMailProgress.log"];
credentials: LIST OF MailUtils.Credentials ¬
MailUtils.GetUserCredentials[
SELECT TRUE FROM ( gvMail AND xnsMail ) => NIL,
gvMail => $gv, xnsMail => $xns, ENDCASE => $xns];
FS.SetKeep[progressLog, 5 ! FS.Error => CONTINUE];
IF wH.newMailRetrievalStream =
NIL
THEN
IF progress
THEN {
wH.newMailRetrievalViewer ¬ TypeScript.Create[
info: [name: "NewMail Retrieval", iconic: FALSE, column: right, openHeight: 64],
paint: FALSE];
ViewerOps.TopViewer[viewer: wH.newMailRetrievalViewer, paint: TRUE];
wH.newMailRetrievalViewer.inhibitDestroy ¬ TRUE;
wH.newMailRetrievalStream ¬ ViewerIO.CreateViewerStreams[
name: NIL, viewer: wH.newMailRetrievalViewer, backingFile: progressLog].out;
}
ELSE {
of: FS.OpenFile = FS.Create[progressLog, TRUE, 2, TRUE, 5];
wH.newMailRetrievalStream ¬ FS.StreamFromOpenFile[of, $write];
};
WalnutNewMail.EnableMailRetrieval[
opsHandle: wH.opsH,
registeredUsers: credentials,
reportProc: ReportProc,
progressProc: ProgressReport,
getMailLog: GetMailLog,
recordMailInfo: RecordNewMailInfo,
notifyWhenMailRetrieved: NotifyWhenMailRetrieved];
IF wH.newMailRetrievalViewer # NIL THEN
wH.newMailRetrievalViewer.inhibitDestroy ¬ FALSE;
};
DisableNewMail:
PUBLIC
PROC[wH: WalnutHandle] = {
IF NOT wH.personalMailDB THEN RETURN;
WalnutNewMail.DisableMailRetrieval[wH.opsH];
IF wH.newMailRetrievalStream #
NIL
THEN {
IF wH.newMailRetrievalViewer =
NIL
THEN wH.newMailRetrievalStream.Close[]
ELSE
IF ~wH.newMailRetrievalViewer.destroyed
THEN {
wH.newMailRetrievalStream.Close[];
ViewerOps.DestroyViewer[wH.newMailRetrievalViewer];
};
wH.newMailRetrievalStream ¬ NIL;
wH.newMailRetrievalViewer ¬ NIL;
wH.personalMailDB ¬ FALSE;
};
};
tempName: ROPE = "/tmp/Walnut.TypescriptLog";
* * * * * * * * * * support for new mail
newMailCount: CARDINAL ¬ 0;
newMailProgressTimeToFlush: CARDINAL ¬ 10;
ReportProc: WalnutDefs.CheckReportProc = {
wH: WalnutHandle = CheckMailHandle[opsH];
IF wH # NIL THEN ReportFormat[wH, format, v1, v2, v2];
};
ProgressReport: WalnutDefs.CheckReportProc = {
wH: WalnutHandle = CheckMailHandle[opsH];
IF wH = NIL THEN RETURN;
IF wH.newMailRetrievalViewer #
NIL
THEN
IF wH.newMailRetrievalViewer.destroyed
THEN {
wH.newMailRetrievalViewer ¬ NIL;
wH.newMailRetrievalStream ¬ NIL;
};
IF wH.newMailRetrievalStream #
NIL
THEN {
wH.newMailRetrievalStream.PutF[format, v1, v2, v3];
IF (newMailCount ¬ newMailCount + 1) > newMailProgressTimeToFlush
THEN {
newMailCount ¬ 0;
wH.newMailRetrievalStream.Flush[];
};
};
};
GetMailLog:
PROC[opsHandle: WalnutOps.WalnutOpsHandle]
RETURNS[strm:
STREAM] = {
wH: WalnutHandle = CheckMailHandle[opsHandle];
outcome: WaitCallOutcome;
Gml:
PROC =
{ strm ¬ WalnutOps.StartNewMail[opsHandle] };
IF wH = NIL THEN RETURN;
IF (outcome ¬ DoWaitCall[wH, Gml]) = ok
THEN {
SetMailState[wH, retrieving];
RETURN;
};
IF outcome = notRunning THEN Process.Pause[Process.SecondsToTicks[10]];
outcome ¬ DoWaitCall[wH, Gml]; -- try again
IF outcome = ok THEN SetMailState[wH, retrieving];
};
RecordNewMailInfo:
PROC[opsHandle: WalnutOps.WalnutOpsHandle, logLen:
INT, server:
ROPE, num:
INT]
RETURNS[ok: BOOL ¬ FALSE] = {
wH: WalnutHandle = CheckMailHandle[opsHandle];
Rnml:
PROC = {
ok ¬ FALSE;
WalnutOps.RecordNewMailInfo[opsHandle, logLen, server, num];
ok ¬ TRUE;
};
IF wH = NIL THEN RETURN[FALSE];
IF wH.opsH # opsHandle
THEN
ERROR WalnutDefs.Error[$control, $WrongOpsHandle, "RecordNewMailInfo"];
[] ¬ DoWaitCall[wH, Rnml];
};
CheckMailHandle:
PROC[opsH: WalnutOps.WalnutOpsHandle]
RETURNS[wH: WalnutHandle] = {
wH ¬ WalnutWindow.GetHandleForMail[];
IF wH = NIL THEN RETURN;
IF wH.opsH # opsH
THEN
ERROR WalnutDefs.Error[$control, $WrongOpsHandle];
};
NotifyWhenMailRetrieved:
PROC[opsHandle: WalnutOps.WalnutOpsHandle, ok:
BOOL, someMail:
BOOL] = {
autoNewMail: BOOL;
wH: WalnutHandle = CheckMailHandle[opsHandle];
IF wH = NIL OR ~wH.personalMailDB THEN RETURN;
IF ~(wH.someMail ¬ someMail) THEN { SetMailState[wH, noMail]; RETURN};
SetMailState[wH, thereIsMail];
autoNewMail ¬ UserProfile.Boolean[key: "Walnut.AutoNewMail", default: FALSE];
IF autoNewMail
THEN
TRUSTED { Process.Detach[FORK GetNewMail[wH] ] };
};
SetMailState:
PUBLIC
PROC[wH: WalnutHandle, mailState: MailState] = {
status: ROPE;
iconState: WalnutWindowPrivate.IconState ¬ regular;
IF wH.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 => {
iconState ¬ haveNewMail;
status ¬ "You have new mail at %g";
};
waiting => status ¬ "Waiting (10 sec) for initial mail server response at %g";
noState => status ¬ "No mailbox state reported at %g";
noServers => status ¬ "All of the mail servers are down at %g";
someMail => status ¬ "Mail on some server(s) at %g";
ENDCASE => NULL;
IF wH.whichIcon # iconState
THEN {
wH.walnut.icon ¬ wH.iconSet[wH.whichIcon ¬ iconState];
IF wH.walnut.iconic THEN ViewerOps.PaintViewer[wH.walnut, all];
};
Labels.Set[wH.mailNotifyLabel, IO.PutFR1[status, [time[BasicTime.Now[]]]] ];
};