WalnutMsgDisplayerImpl.mesa
Copyright Ó 1985, 1988, 1989, 1992 by Xerox Corporation. All rights reserved.
Last Edited by: Willie-Sue, August 23, 1989 11:31:54 am PDT
Doug Terry, October 6, 1992 4:22 pm PDT
Jack Kent April 9, 1987 4:25:25 pm PDT
Pavel, February 6, 1986 3:33:33 pm PST
Donahue, June 17, 1985 4:53:34 pm PDT
Contents: Implementation of the Walnut Msg Display windows.
Swinehar, November 11, 1991 9:10 am PST
Status: complete.
Created by: Rick Cattell & Willie-Sue Haugeland, 17-Feb-82
(Changed StripForIcon to remove all registry information from icon labels)
Rick on: April 13, 1982 11:50 am
Willie-Sue on: January 3, 1985 4:27:53 pm PST
DIRECTORY
Ascii USING [ Letter ],
Atom USING [ GetPName ],
IO,
MailSend USING [ GetRegisteredSendProcsList, MailSendProcsRef],
Menus,
PopUpSelection USING [Request],
Rope,
SendMailOps USING [Answer, CreateRopeForTextNode, CreateSendViewer, Forward, ReSend],
TEditSplit USING[ Split ],
TEditDocument USING [TEditDocumentData, maxClip],
TiogaOps USING [CancelSelection, GetSelection, RestoreSelB, SaveSelB, SelectDocument, SetStyle, ViewerDoc],
TiogaMenuOps USING[ tiogaMenu, AllLevels ],
UserProfile USING [Boolean, ListOfTokens, Token],
ViewerClasses USING [Viewer],
ViewerEvents USING [ EventRegistration, EventProc, ViewerEvent, RegisterEventProc, UnRegisterEventProc ],
ViewerLocks USING[ CallUnderWriteLock ],
ViewerOps USING [AddProp, CreateViewer, DestroyViewer, FetchProp, GrowViewer, OpenIcon, PaintViewer, SetMenu, SetNewVersion],
ViewerTools USING [TiogaContents, EnableUserEdits, InhibitUserEdits, SetTiogaContents],
WalnutFilter USING [MenuExtras],
WalnutOps USING [MsgSet, GetCategories, GetMsgSize, GetMsgShortName, GetMsg, MsgExists],
WalnutViewer USING [CreateMenuEntry],
WalnutInternal USING [AddorAppendTo, DoWaitCall, GetButton, HowToPrint, msgIcon, MsgPrintProc, RemoveFrom],
WalnutWindow USING [GetHandleList, GetRootFileForHandle, Report, ReportFormat, ReportRope],
WalnutWindowPrivate USING [MsgAndHandle, MsgAndHandleRec, MsgSetButton, WalnutHandle, WalnutHandleRec];
WalnutMsgDisplayerImpl: CEDAR MONITOR
IMPORTS
Ascii, Atom, MailSend, PopUpSelection, Rope, SendMailOps,
TiogaMenuOps, TiogaOps, TEditSplit,
Menus, UserProfile, ViewerEvents, ViewerLocks, ViewerOps, ViewerTools,
WalnutFilter,
WalnutOps,
WalnutInternal,
WalnutViewer, WalnutWindow
EXPORTS
WalnutInternal, WalnutWindow
SHARES ViewerClasses =
BEGIN OPEN WalnutInternal;
ROPE: TYPE = Rope.ROPE;
TiogaContents: TYPE = ViewerTools.TiogaContents;
Viewer: TYPE = ViewerClasses.Viewer;
MsgSet: TYPE = WalnutOps.MsgSet;
MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton;
WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle;
WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec;
MsgAndHandle: TYPE = WalnutWindowPrivate.MsgAndHandle;
MsgAndHandleRec: TYPE = WalnutWindowPrivate.MsgAndHandleRec;
pruneHeaders: BOOLEAN ¬ UserProfile.Boolean["Walnut.PruneHeaders", FALSE];
unprunedHeaders: LIST OF ROPE ¬ UserProfile.ListOfTokens["Walnut.UnprunedHeaders", LIST["subject", "from", "to", "cc", "date"]];
--------------------------
exported to WalnutWindow
GetMsgName: PUBLIC PROC[v: Viewer] RETURNS[mName: ROPE, rootFile: ROPE] = {
of v is a Viewer for a Walnut Entity, then return its name else NIL
msgAndWH: MsgAndHandle = NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]];
IF msgAndWH = NIL THEN RETURN;
rootFile ¬ WalnutWindow.GetRootFileForHandle[msgAndWH.wH];
RETURN[msgAndWH.msg, rootFile];
};
InternalAddToMsgMenu: PUBLIC PROC[wH: WalnutHandle, label: ROPE, proc: Menus.MenuProc, clientData: REF ANY ¬ NIL, onQueue: BOOL] = {
FOR wHL: LIST OF WalnutHandle ¬ (IF wH # NIL THEN LIST[wH] ELSE WalnutWindow.GetHandleList[]), wHL.rest UNTIL wHL = NIL DO
new: Menus.MenuEntry = IF onQueue THEN
WalnutViewer.CreateMenuEntry[wHL.first.walnutQueue, label, proc, clientData]
ELSE Menus.CreateEntry[label, proc, clientData];
Menus.AppendMenuEntry[wHL.first.msgMenu, new];
Menus.AppendMenuEntry[wHL.first.frozenMsgMenu, Menus.CopyEntry[new]];
ChangeMsgMenus[wHL.first];
ENDLOOP;
};
InternalReplaceInMsgMenu: PUBLIC PROC[wH: WalnutHandle, label: ROPE, proc: Menus.MenuProc, clientData: REF ANY ¬ NIL, onQueue: BOOL]
RETURNS[oldFound: BOOL] = {
DoReplace: PROC[thisMenu: Menus.Menu] RETURNS[foundIt: BOOL ¬ TRUE]= {
old: Menus.MenuEntry = Menus.FindEntry[thisMenu, label];
new: Menus.MenuEntry = IF onQueue THEN
WalnutViewer.CreateMenuEntry[wH.walnutQueue, label, proc, clientData]
ELSE Menus.CreateEntry[label, proc, clientData];
Menus.ReplaceMenuEntry[thisMenu, old, new ! Menus.targetNotFound =>
{ foundIt ¬ FALSE ; CONTINUE }];
IF NOT foundIt THEN Menus.AppendMenuEntry[thisMenu, new];
};
FOR wHL: LIST OF WalnutHandle ¬ (IF wH # NIL THEN LIST[wH] ELSE WalnutWindow.GetHandleList[]), wHL.rest UNTIL wHL = NIL DO
old: Menus.MenuEntry = Menus.FindEntry[wH.msgMenu, label];
thisFound: BOOL;
oldFound ¬ DoReplace[wH.msgMenu];
thisFound ¬ DoReplace[wH.frozenMsgMenu];
oldFound ¬ thisFound AND oldFound;
ChangeMsgMenus[wH];
ENDLOOP;
};
RemoveFromMsgMenu: PUBLIC PROC[wH: WalnutHandle, name: ROPE] = {
FOR wHL: LIST OF WalnutHandle ¬ (IF wH # NIL THEN LIST[wH] ELSE WalnutWindow.GetHandleList[]), wHL.rest UNTIL wHL = NIL DO
old: Menus.MenuEntry ¬ Menus.FindEntry[wHL.first.msgMenu, name];
IF old # NIL THEN
Menus.ReplaceMenuEntry[wHL.first.msgMenu, old ! Menus.targetNotFound => CONTINUE ];
old ¬ Menus.FindEntry[wHL.first.frozenMsgMenu, name];
IF old # NIL THEN
Menus.ReplaceMenuEntry[wHL.first.frozenMsgMenu, old ! Menus.targetNotFound => CONTINUE ];
ChangeMsgMenus[wH];
ENDLOOP;
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
QDisplayMsg: PUBLIC PROC[wH: WalnutHandle, msg: ROPE, oldV: Viewer, shift, openIfIconic, paint: BOOL] RETURNS[v: Viewer] = {
contents: TiogaContents;
herald, shortName: ROPE;
iconName, date: ROPE;
maH: MsgAndHandle = NEW[MsgAndHandleRec ¬ [msg, wH]];
LockedSetMenu: PROC = {
ViewerOps.SetMenu[v, wH.msgMenu];
IF UserProfile.Boolean["Walnut.MsgViewerPlaces", FALSE] THEN MsgPlacesProc[v, NIL, $red];
};
IF ~WalnutOps.MsgExists[wH.opsH, msg] THEN RETURN[NIL];
[contents, herald, shortName] ¬ WalnutOps.GetMsg[wH.opsH, msg];
contents ¬ PruneHeaderFields[contents];
herald ¬ wH.identifierPrefix.Concat[herald];
iconName ¬ Rope.Substr[shortName, 0, shortName.Length[] - 9];
date ¬ Rope.Substr[shortName, shortName.Length[] - 9];
IF oldV # NIL AND ~oldV.destroyed THEN {
oldV.name ¬ herald;
ViewerOps.PaintViewer[oldV, caption];
v ¬ oldV;
}
ELSE {
v ¬ ViewerOps.CreateViewer[flavor: $Text, paint: paint,
 info: [name: herald, icon: msgIcon,
  scrollable: TRUE, iconic: FALSE] ];
wH.msgViewerList ¬ CONS[v, wH.msgViewerList];
ViewerLocks.CallUnderWriteLock[LockedSetMenu, v];
IF shift THEN ViewerOps.GrowViewer[v];
shift ¬ FALSE;  -- so don't end up toggling the Grow
ViewerOps.AddProp[v, $DestroyMsgDisplayer,
ViewerEvents.RegisterEventProc[DestroyMsgDisplayer, destroy, v]];
};
ViewerOps.AddProp[v, $WalnutMsgName, maH ];
Note how we cleverly put in a "." here to get the date to appear on a new line
v.label ¬ Rope.Cat[wH.identifierPrefix, StripForIcon[iconName], " .", date];
ShowMsgInMsgViewer[v, contents, shift, openIfIconic, paint];
};
FixUpMsgViewer: PUBLIC PROC[wH: WalnutHandle, msg: ROPE, v: Viewer] = {
IF (msg.Length[] = 0) OR v.destroyed THEN RETURN;
IF QDisplayMsg[wH, msg, v, FALSE, TRUE, TRUE].v = NIL THEN {
WalnutWindow.ReportFormat[wH,
 "Msg: %g doesn't exist; destroying viewer", [rope[msg]] ];
ViewerOps.DestroyViewer[v];
};
};
DisplayMsgFromMsgSet: PUBLIC PROC[wH: WalnutHandle, msg: ROPE, msViewer: Viewer, shift: BOOL] = {
v: Viewer = NARROW[ViewerOps.FetchProp[msViewer, $LastSpawned]];
newV: Viewer;
newV ¬ QDisplayMsg[wH, msg, v, shift, TRUE, TRUE];
IF newV = v THEN RETURN;
ViewerOps.AddProp[newV, $WhoSpawnedMe, msViewer];
ViewerOps.AddProp[msViewer, $LastSpawned, newV];
};
***********************************************************
menu command procs:
MsgForwardProc: Menus.MenuProc = {
self: Viewer ¬ NARROW[parent];
fw: Viewer;
self.inhibitDestroy ¬ TRUE;
fw ¬ SendMailOps.Forward[self, self];
IF UserProfile.Boolean["Walnut.EditedForwardSenders", FALSE] OR mouseButton = blue THEN
 ViewerOps.SetNewVersion[fw];
self.inhibitDestroy ¬ FALSE;
};
MsgReSendProc: Menus.MenuProc = {
self: Viewer ¬ NARROW[parent];
self.inhibitDestroy ¬ TRUE;
[] ¬ SendMailOps.ReSend[self, self];
self.inhibitDestroy ¬ FALSE;
};
MsgAnswerProc: Menus.MenuProc = {
OPEN TiogaOps;
self: Viewer ¬ NARROW[parent];
transport: ATOM ¬ NARROW[clientData];
ans: Viewer;
msgR: ROPE;
self.inhibitDestroy ¬ TRUE;
TRUSTED { msgR ¬ SendMailOps.CreateRopeForTextNode[LOOPHOLE[ViewerDoc[self]]]};
ans ¬ SendMailOps.Answer[msgR, self, transport];
IF UserProfile.Boolean["Walnut.EditedAnswerSenders", FALSE] OR mouseButton = blue THEN
 ViewerOps.SetNewVersion[ans];
self.inhibitDestroy ¬ FALSE;
};
MsgOpsProc: Menus.MenuProc = {
ChoicesFromMenuEntry: PROC [me: Menus.MenuEntry] RETURNS [choices: LIST OF ROPE] ~ {
l: LIST OF ROPE ¬ NIL;
IF me = NIL THEN RETURN[NIL];
choices ¬ LIST[me.name];
me ¬ me.link;
l ¬ choices;
WHILE me # NIL DO
l.rest ¬ LIST[me.name];
me ¬ me.link;
l ¬ l.rest;
ENDLOOP;
};
ConcatLists: PROC [l1, l2: LIST OF ROPE] RETURNS [LIST OF ROPE] ~ {
l: LIST OF ROPE ¬ l1;
WHILE l.rest # NIL DO l ¬ l.rest; ENDLOOP;
l.rest ¬ l2;
RETURN[l1];
};
self: Viewer = NARROW[parent];
msgAndwH: MsgAndHandle = NARROW[ViewerOps.FetchProp[self, $WalnutMsgName]];
msg: ROPE = msgAndwH.msg;
wH: WalnutHandle = msgAndwH.wH;
choices: LIST OF ROPE ¬
LIST["Sender", "Categories", "AddTo", "Remove From ...", "SizeOf", "msgID",
"Toggle Header Pruning", "Interpress2.0Print", "Interpress3.0Print", "MakeEditable"];
moreChoices: LIST OF ROPE;
moreProcs: Menus.MenuEntry;
which: INT;
moreProcs ¬ WalnutFilter.MenuExtras[$msgops];
moreChoices ¬ ChoicesFromMenuEntry[moreProcs];
choices ¬ ConcatLists[choices, moreChoices];
which ¬ PopUpSelection.Request["MsgOps", choices];
SELECT which FROM
1 => [] ¬ SendMailOps.CreateSendViewer[fromExec: FALSE];
2 => [] ¬ PopUpCategories[self, wH, msg]; -- Categories
3 => {  -- AddTo
mL: LIST OF ROPE = WalnutOps.GetCategories[wH.opsH, msg];
from: MsgSetButton = GetButton[wH, mL.first];
FOR mlx: MsgSetButton ¬ wH.selectedMsgSetButtons, mlx.selected UNTIL mlx = NIL DO
AddorAppendTo[wH: wH, msg: msg, isAdd: TRUE, fromButton: from, toButton: mlx];
ENDLOOP;
};
4 => {  -- Remove From ...
mL: LIST OF ROPE;
which: INT;
from: ROPE;
[which, mL] ¬ PopUpCategories[self, wH, msg];
IF which = 0 THEN RETURN;
FOR i: INT IN [1..which] DO
from ¬ mL.first;
mL ¬ mL.rest;
ENDLOOP;
RemoveFrom[msg, GetButton[wH, from]];
};
5 => {
textLen, formatLen: INT;
[textLen, formatLen] ¬ WalnutOps.GetMsgSize[wH.opsH, msg];
IF formatLen # 0 THEN
WalnutWindow.ReportFormat[wH, "Formatted Msg \" %g\" has %g bytes of text\n",
 [rope[msg]], [integer[textLen]] ]
ELSE WalnutWindow.ReportFormat[wH, "Msg \"%g\" has %g bytes of text\n",
 [rope[msg]], [integer[textLen]] ];
};
6 => MsgGvId[wH, msg, mouseButton # red];
7 => ToggleHeaderPruning[self, wH, msg];
8 => MsgPrint[wH: wH, self: self, howToPrint: ip2];
9 => MsgPrint[wH: wH, self: self, howToPrint: ip3];
10 => {
MsgFreezeProc[parent];
ViewerTools.EnableUserEdits[self];
};
ENDCASE => IF moreChoices # NIL THEN {
i: INT ¬ 11;
plist: Menus.MenuEntry ¬ moreProcs;
WHILE i < which AND plist # NIL DO
i ¬ i + 1;
plist ¬ plist.link;
ENDLOOP;
IF i = which AND plist # NIL THEN
plist.proc[parent, clientData, mouseButton, shift, control];
};
};
PopUpCategories: PROC[self: Viewer, wH: WalnutHandle, msg: ROPE]
RETURNS[which: INT, mL: LIST OF ROPE] = {
IF ViewerOps.FetchProp[self, $Frozen] # NIL AND ~WalnutOps.MsgExists[wH.opsH, msg] THEN {
WalnutWindow.ReportFormat[wH,
"Msg %g in a frozen viewer doesn't exist in this database", [rope[msg]] ];
RETURN[0, NIL]
};
which ¬ PopUpSelection.Request["Categories", mL ¬ WalnutOps.GetCategories[wH.opsH, msg] ];
};
MsgFreezeProc: Menus.MenuProc = {
self: Viewer = NARROW[parent];
msViewer: Viewer = NARROW[ViewerOps.FetchProp[self, $WhoSpawnedMe]];
frozen: Menus.MenuEntry = Menus.FindEntry[self.menu, "Freeze"];
IF frozen # NIL THEN FreezeViewer[self];
now freeze everyone linked to you
IF self.link # NIL THEN -- you are part of a split viewer
FOR newV: Viewer ¬ self.link, newV.link UNTIL newV = self DO
FreezeViewer[newV]
ENDLOOP;
only need to do this once
IF msViewer # NIL THEN ViewerOps.AddProp[msViewer, $LastSpawned, NIL]
};
FreezeViewer: PROC[ v: Viewer ] = {
msgAndwH: MsgAndHandle = NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]];
ViewerOps.AddProp[ v, $Frozen, v ];
ViewerOps.SetMenu[v, msgAndwH.wH.frozenMsgMenu];
};
MsgSplitProc: Menus.MenuProc = {
self: Viewer = NARROW[parent];
newV: Viewer;
frozen: REF ANY = ViewerOps.FetchProp[self, $Frozen];
TEditSplit.Split[self];
now find the newest link in the chain to copy properties
FOR newV ¬ self.link, newV.link UNTIL newV.link = self DO ENDLOOP;
ViewerOps.AddProp[
newV, $WalnutMsgName, ViewerOps.FetchProp[self, $WalnutMsgName] ];
ViewerOps.AddProp[
newV, $WhoSpawnedMe, ViewerOps.FetchProp[ self, $WhoSpawnedMe ] ];
IF frozen # NIL THEN FreezeViewer[newV]
ELSE ViewerOps.AddProp[ newV, $DestroyMsgDisplayer,
ViewerEvents.RegisterEventProc[DestroyMsgDisplayer, destroy, newV] ];
newV.icon ¬ msgIcon;
};
DestroyMsgDisplayer: ViewerEvents.EventProc = {
eventProc: ViewerEvents.EventRegistration;
next: Viewer = viewer.link;
spawner: Viewer = NARROW[ ViewerOps.FetchProp[viewer, $WhoSpawnedMe] ];
IF ViewerOps.FetchProp[viewer, $Frozen] # NIL THEN RETURN; -- you're not involved
IF spawner # NIL THEN ViewerOps.AddProp[ spawner, $LastSpawned, next ];
eventProc ¬ NARROW[ ViewerOps.FetchProp[viewer, $DestroyMsgDisplayer]];
ViewerEvents.UnRegisterEventProc[ eventProc, destroy]; };
MsgPlacesProc: Menus.MenuProc =
Menus.CopyEntry[ Menus.FindEntry[ TiogaMenuOps.tiogaMenu, "Places" ] ].proc;
MsgLevelsProc: Menus.MenuProc =
Menus.CopyEntry[ Menus.FindEntry[ TiogaMenuOps.tiogaMenu, "Levels" ] ].proc;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
MsgCategories: PUBLIC PROC[wH: WalnutHandle, msg: ROPE] = {
Mc: PROC = {
msL: LIST OF ROPE ¬ WalnutOps.GetCategories[wH.opsH, msg];
first: BOOL ¬ TRUE;
shortName: ROPE = WalnutOps.GetMsgShortName[wH.opsH, msg];
WalnutWindow.ReportFormat[wH, " %g is in: ", [rope[shortName]] ];
IF msL = NIL THEN
{ WalnutWindow.Report[wH, "no MsgSets! This is a bug."]; RETURN };
FOR mL: LIST OF ROPE ¬ msL, mL.rest UNTIL mL=NIL DO
IF first THEN first ¬ FALSE ELSE WalnutWindow.ReportRope[wH, ", "];
WalnutWindow.ReportRope[wH, mL.first];
ENDLOOP;
WalnutWindow.ReportRope[wH, "\n"];
};
[] ¬ DoWaitCall[wH, Mc];
};
MsgGvId: PUBLIC PROC[wH: WalnutHandle, msg: ROPE, all: BOOL] = {
Mg: PROC = {
WalnutWindow.Report[wH, "gv postmark for msg is: ", msg];
};
[] ¬ DoWaitCall[wH, Mg];
};
MsgPrint: PROC[wH: WalnutHandle, self: Viewer, howToPrint: HowToPrint] = {
Mp: PROC = { MsgPrintProc[wH, self, howToPrint] };
[] ¬ DoWaitCall[wH, Mp];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
ChangeMsgMenus: PROC[wH: WalnutHandle] = {
-- a menu was changed - update all msg viewers for wH
FOR vL: LIST OF Viewer ¬ wH.msgViewerList, vL.rest UNTIL vL = NIL DO
msgAndWH: MsgAndHandle;
v: Viewer = vL.first;
IF v.destroyed THEN LOOP;
msgAndWH ¬ NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]];
IF ViewerOps.FetchProp[v, $Frozen] = NIL THEN
ViewerOps.SetMenu[v, wH.msgMenu]
ELSE ViewerOps.SetMenu[v, wH.frozenMsgMenu];
ENDLOOP;
};
plainTextStyle: PUBLIC ROPE ¬ UserProfile.Token[key: "Walnut.PlainTextStyle", default: "cedar"];
ShowMsgInMsgViewer: PROC[v: Viewer, contents: TiogaContents, shift, open, paint: BOOL] = {
painted: BOOL ¬ FALSE;
KillFeedbackSel[v];
IF v.link # NIL THEN DestroySplitMsgDisplayers[v];
check to see whether AllLevels will cause a paint
BEGIN
WITH v.data SELECT FROM
tdd: TEditDocument.TEditDocumentData =>
IF tdd.clipLevel # TEditDocument.maxClip THEN painted ¬ TRUE
ENDCASE;
END;
IF contents.formatting.IsEmpty[]
AND NOT Rope.Equal[plainTextStyle, "cedar"] THEN { -- Plain Text
ViewerTools.SetTiogaContents[v, contents, FALSE];
TiogaOps.SaveSelB[];
TiogaOps.SelectDocument[viewer: v, level: point];
TiogaOps.SetStyle[plainTextStyle, root];
v.newVersion ¬ FALSE; -- Is there a ``better'' way to do this?
IF paint THEN ViewerOps.PaintViewer[v, all];
TiogaOps.RestoreSelB[];
}
ELSE { -- Tioga formatted; needn't reset the style
ViewerTools.SetTiogaContents[v, contents, NOT painted AND paint];
TiogaMenuOps.AllLevels[v];
};
ViewerTools.InhibitUserEdits[v];
IF v.iconic THEN {
IF ~open THEN
RETURN;
ViewerOps.OpenIcon[v, shift]
}
ELSE IF shift THEN
ViewerOps.GrowViewer[v]
};
bug in SetTiogaContents necessitates this
KillFeedbackSel: PROC[v: Viewer] = {
OPEN TiogaOps;
who: Viewer ¬ GetSelection[feedback].viewer;
IF who = v THEN CancelSelection[feedback];
};
DestroySplitMsgDisplayers: ENTRY PROC[keepThisOne: Viewer] = {
ENABLE UNWIND => NULL;
next: Viewer ¬ keepThisOne.link;
next2: Viewer;
event: ViewerEvents.EventRegistration;
DO
IF next = keepThisOne THEN EXIT;
IF (event ¬ NARROW[ViewerOps.FetchProp[next, $DestroyMsgDisplayer]]) = NIL THEN LOOP;
ViewerEvents.UnRegisterEventProc[event, destroy];
next2 ¬ next.link;
ViewerOps.DestroyViewer[next];  -- DON'T FORK here
next ¬ next2;
ENDLOOP;
};
StripForIcon: PROC[name: ROPE] RETURNS[ iconLabel: ROPE ] = {
start: INT;
dot: INT;
suffixLength: NAT;
Remove all registry information from the icon label -- where registry information is taken to be any sequence of letters following a period
start ¬ 0;
WHILE (dot ¬ Rope.Find[Rope.Substr[name, start], "."]) # -1 DO
length: INT = Rope.Length[name];
dot ¬ dot+start;
IF length - dot < 2 THEN EXIT;
suffixLength ¬ 0;
WHILE dot+1+suffixLength < length AND
Ascii.Letter[Rope.Fetch[name, dot+1+suffixLength]] DO
suffixLength ¬ suffixLength+1
ENDLOOP;
IF suffixLength >= 0 THEN
{ name ¬ Rope.Replace[name, dot, suffixLength+1]; start ¬ dot }
ELSE start ¬ dot+suffixLength+1
ENDLOOP;
iconLabel ¬ Rope.Substr[name, 0, Rope.Length[name]-1]
};
PruneHeaderFields: PROC [msg: TiogaContents] RETURNS [new: TiogaContents] ~ {
Removes uninteresting header fields from the message.
Currently, this is only done for non-Tioga-formatted messages. Pruning formatted headers is more difficult since the formatting as well as the contents must be modified. ...DBT
start, end: INT;
contents: ROPE ¬ msg.contents;
keptHeader: BOOLEAN ¬ FALSE;
IF NOT pruneHeaders OR NOT Rope.IsEmpty[msg.formatting] THEN RETURN[msg];
start ¬ 0;
end ¬ Rope.SkipTo[s: contents, pos: start, skip: "\n\r\l"];
WHILE start < end DO -- while not end of header
IF NOT (Rope.Fetch[contents, start] = ' OR Rope.Fetch[contents, start] = '\t) THEN { -- new header line (not continuation of previous header)
keptHeader ¬ FALSE;
FOR uphL: LIST OF ROPE ← unprunedHeaders, uphL.rest WHILE uphL # NIL AND keptHeader = FALSE DO
IF Rope.IsPrefix[prefix: uphL.first, subject: Rope.Substr[contents, start], case: FALSE] THEN
keptHeader ¬ TRUE;
ENDLOOP;
};
IF NOT keptHeader
THEN contents ¬ Rope.Replace[base: contents, start: start, len: end-start+1, with: NIL]
ELSE start ¬ end + 1;
end ¬ Rope.SkipTo[s: contents, pos: start, skip: "\n\r\l"];
ENDLOOP;
msg.contents ¬ contents;
RETURN[msg];
};
ToggleHeaderPruning: PROC [self: Viewer, wH: WalnutHandle, msg: ROPE] RETURNS [] ~ {
IF pruneHeaders
THEN {
pruneHeaders ¬ FALSE;
WalnutWindow.Report[wH, "Header pruning turned off."];
}
ELSE {
pruneHeaders ¬ TRUE;
unprunedHeaders ¬ UserProfile.ListOfTokens["Walnut.UnprunedHeaders", LIST["subject", "from", "to", "cc", "date"]];
WalnutWindow.Report[wH, "Header pruning turned on."];
};
[] ¬ QDisplayMsg[wH: wH, msg: msg, oldV: self, shift: FALSE, openIfIconic: TRUE, paint: TRUE];
};
CreateMsgMenu: PUBLIC PROC[wH: WalnutHandle] = {
OPEN Menus;
added: Menus.MenuEntry;
msgMenu: Menus.Menu ¬ Menus.CreateMenu[];
frozenMsgMenu: Menus.Menu ¬ Menus.CreateMenu[];
AppendMenuEntry[ msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "Freeze", MsgFreezeProc]];
do both msgMenu & frozenMsgMenu
FOR procs: LIST OF MailSend.MailSendProcsRef ¬ MailSend.GetRegisteredSendProcsList[],
procs.rest UNTIL procs = NIL DO
name: ROPE ¬ Rope.Concat[Atom.GetPName[procs.first.which], "Answer"];
Menus.AppendMenuEntry[ msgMenu,
Menus.CreateEntry[name: name, proc: MsgAnswerProc, clientData: procs.first.which]];
Menus.AppendMenuEntry[ frozenMsgMenu,
Menus.CreateEntry[name: name, proc: MsgAnswerProc, clientData: procs.first.which]];
ENDLOOP;
AppendMenuEntry[msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "Forward", MsgForwardProc]];
AppendMenuEntry[msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "ReSend", MsgReSendProc]];
AppendMenuEntry[msgMenu, Menus.CreateEntry["MsgOps", MsgOpsProc]];
AppendMenuEntry[ msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "Split", MsgSplitProc]];
AppendMenuEntry[ msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "Places", MsgPlacesProc]];
AppendMenuEntry[ msgMenu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "Levels", MsgLevelsProc]];
added ¬ WalnutFilter.MenuExtras[$msg];
UNTIL added = NIL DO
me: Menus.MenuEntry ¬ added;
added ¬ added.link;
Menus.AppendMenuEntry[msgMenu, me];
ENDLOOP;
wH.msgMenu ¬ msgMenu;
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Forward", MsgForwardProc]];
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["ReSend", MsgReSendProc]];
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["MsgOps", MsgOpsProc]];
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Split", MsgSplitProc]];
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Places", MsgPlacesProc]];
AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Levels", MsgLevelsProc]];
added ¬ WalnutFilter.MenuExtras[$msg];
UNTIL added = NIL DO
me: Menus.MenuEntry ¬ added;
added ¬ added.link;
Menus.AppendMenuEntry[frozenMsgMenu, me];
ENDLOOP;
wH.frozenMsgMenu ¬ frozenMsgMenu;
};
END.
Change Log.
WSH on March 4, 1983: take out all DBText stuff