WalnutPrintImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Willie-Sue, November 7, 1985 12:29:04 pm PST
Contents: Implementation of printing of Msgs, MsgSets, MsgSetTOC's (someday)
Status: mostly here functionally, but not yet completed.
Created by: Willie-Sue, June 29, 1983
Last edit by:
Willie-Sue on: December 27, 1984 2:45:23 pm PST
DIRECTORY
IO USING [Error],
Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc],
PrincOpsUtils USING [IsBound],
Process USING [Detach],
Rope,
PutGet USING [FromRope],
TextEdit USING [SetLooks],
TextLooks USING [Looks, noLooks],
TextNode USING [Ref],
TiogaFileOps USING [CreateRoot, Ref, SetContents, SetFormat],
TiogaOps USING [Ref, FirstChild, LastLocWithin, PutProp],
TSExtras USING [PrintSuppliedNodes, PrintTiogaViewer, NodeProc],
TSTranslate USING [FontNotFound],
ViewerOps USING [AddProp, FetchProp, SetMenu],
ViewerTools USING [TiogaContents],
UserProfile USING [Boolean],
ViewerClasses USING [Viewer],
WalnutDefs USING [Error],
WalnutOps USING [MsgsInSetEnumeration, GetDisplayProps, GetMsg, MsgExists, SizeOfMsgSet],
WalnutPrintOps USING [],
WalnutControlInternal USING [workingMenu, ChangeMenu],
WalnutWindowInternal USING [walnut, Report, ReportRope];
WalnutPrintImpl: CEDAR MONITOR
IMPORTS
IO, Menus, PrincOpsUtils, Process, Rope, ViewerOps, UserProfile,
PutGet, TextEdit, TiogaFileOps, TiogaOps, TSExtras, TSTranslate,
WalnutDefs, WalnutOps,
WalnutControlInternal, WalnutWindowInternal
EXPORTS
WalnutPrintOps =
BEGIN OPEN WalnutWindowInternal;
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
blankMenu: PUBLIC Menus.Menu = Menus.CreateMenu[];
printingMenu: Menus.Menu ← Menus.CreateMenu[];
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PrintCallReturned: CONDITION;
PrintingInfoObject: TYPE = RECORD[done: BOOL, abortRef: REF BOOL, allOK: BOOLTRUE];
PrintingInfo: TYPE = REF PrintingInfoObject;
lastReportFromPrinter: ROPENIL;
prints msgset, using the msgset viewer
MsgSetPrintProc: PUBLIC ENTRY Menus.MenuProc =
BEGIN ENABLE UNWIND => NULL;
self: Viewer = NARROW[parent];
prevMenu: Menus.Menu ← self.menu;
BEGIN ENABLE UNWIND => CONTINUE;
aborted: REF BOOL = NEW[BOOLFALSE];
printInfo: PrintingInfo;
msgSet: ROPE;
IF ~TSetterAvailable[] THEN RETURN;
msgSet ← NARROW[ViewerOps.FetchProp[self, $WalnutMsgSetName]];
IF ~AnyMessages[msgSet] THEN RETURN;
printInfo ← NEW[PrintingInfoObject ← [done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[self, $PrintingInfo, printInfo];
self.inhibitDestroy ← TRUE;
TRUSTED {Process.Detach[FORK PrintMSProc[msgSet, printInfo]]};
ViewerOps.SetMenu[self, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
END;
ViewerOps.SetMenu[self, prevMenu];
self.inhibitDestroy ← FALSE;
END;
MsgPrintProc: PUBLIC ENTRY Menus.MenuProc =
BEGIN ENABLE UNWIND => NULL;
self: Viewer = NARROW[parent];
prevMenu: Menus.Menu ← self.menu;
msg: ROPE = NARROW[ViewerOps.FetchProp[self, $WalnutMsgName]];
IF ViewerOps.FetchProp[self, $Frozen] # NIL AND ~WalnutOps.MsgExists[msg] THEN {
WalnutWindowInternal.Report[
"Msg ", msg, " in a frozen viewer doesn't exist in this database"];
RETURN
};
IF ~TSetterAvailable[] THEN RETURN;
BEGIN ENABLE UNWIND => CONTINUE;
aborted: REF BOOL = NEW[BOOLFALSE];
printInfo: PrintingInfo;
printInfo ← NEW[PrintingInfoObject ← [done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[self, $PrintingInfo, printInfo];
self.inhibitDestroy ← TRUE;
Report["Printing the msg: ", self.name];
TRUSTED {Process.Detach[FORK PrintViewer[self, printInfo]]};
ViewerOps.SetMenu[self, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
END;
ViewerOps.SetMenu[self, prevMenu];
self.inhibitDestroy ← FALSE;
END;
PrintMsgSet: PUBLIC ENTRY PROC[msgSet: ROPE] RETURNS[allOK: BOOL] =
BEGIN ENABLE UNWIND => NULL;
printInfo: PrintingInfo;
IF ~TSetterAvailable[] THEN RETURN;
IF ~AnyMessages[msgSet] THEN RETURN;
BEGIN ENABLE UNWIND => CONTINUE;
aborted: REF BOOL = NEW[BOOLFALSE];
printInfo ← NEW[PrintingInfoObject ← [done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[walnut, $PrintingInfo, printInfo];
walnut.inhibitDestroy ← TRUE;
TRUSTED {Process.Detach[FORK PrintMSProc[msgSet, printInfo]]};
WalnutControlInternal.ChangeMenu[printingMenu, TRUE];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
END;
walnut.inhibitDestroy ← FALSE;
RETURN[printInfo.allOK];
END;
PrintMsgList: PUBLIC ENTRY PROC[mList: LIST OF ROPE, msViewer: Viewer]
RETURNS[allOK: BOOL] =
BEGIN ENABLE UNWIND => NULL;
prevMenu: Menus.Menu ← msViewer.menu;
printInfo: PrintingInfo;
IF ~TSetterAvailable[] THEN RETURN;
IF mList = NIL THEN RETURN;
BEGIN ENABLE UNWIND => CONTINUE;
aborted: REF BOOL = NEW[BOOLFALSE];
printInfo ← NEW[PrintingInfoObject ← [done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[msViewer, $PrintingInfo, printInfo];
msViewer.inhibitDestroy ← TRUE;
Report["Printing selected msgs from ", msViewer.name];
Report["Printing selected msg from ", msViewer.name];
TRUSTED {Process.Detach[FORK PrintML[mList, msViewer.name, printInfo]]};
ViewerOps.SetMenu[msViewer, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
END;
ViewerOps.SetMenu[msViewer, prevMenu];
msViewer.inhibitDestroy ← FALSE;
RETURN[printInfo.allOK];
END;
TSetterAvailable: INTERNAL PROC RETURNS[ok: BOOL] =
BEGIN
TRUSTED { ok ← PrincOpsUtils.IsBound[LOOPHOLE[TSExtras.PrintTiogaViewer]]};
IF ~ok THEN {
Report["You must load TSetter to be able to print; type TSetter to a commandTool"];
Report["Then try the Print again"];
RETURN[FALSE]
};
RETURN[TRUE];
END;
AnyMessages: PROC[msgSet: ROPE] RETURNS[any: BOOL] = {
IF any ← (WalnutOps.SizeOfMsgSet[msgSet].messages # 0) THEN RETURN;
Report["Msgset: ", msgSet, " contains no msgs"];
};
prints msg displayed in viewer
PrintViewer: PROC [viewer: Viewer, printInfo: PrintingInfo] =
BEGIN ENABLE UNWIND => {SignalPrintDone[printInfo]};
lastReportFromPrinter ← NIL;
TRUSTED {TSExtras.PrintTiogaViewer[viewer: viewer, nameForSeparatorPage: viewer.name,
aborted: printInfo.abortRef, messageProc: PrintReport !
TSTranslate.FontNotFound =>
{ printInfo.abortRef^ ← TRUE; ReportRope[fontName];
Report[" not found - aborting"]; CONTINUE}]};
SignalPrintDone[printInfo];
END;
prints msgset
lotaStars: ROPE = "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n";
PrintMSProc: PROC [msgSet: ROPE, printInfo: PrintingInfo] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msL: LIST OF ROPE;
msg: ROPE;
firstCall: BOOLTRUE;
firstMsg: BOOLTRUE;
newPage, smallHeaders: BOOL;
SupplyMsg: TSExtras.NodeProc = {
IF firstCall THEN
{ node ← FirstNode[rootName];
firstCall ← FALSE;
RETURN
};
IF msL = NIL THEN RETURN[NIL];
ReportProgress[firstMsg];
node ← FormatMsg[msg ← msL.first, firstMsg, newPage, smallHeaders];
msL ← msL.rest;
firstMsg ← FALSE;
};
rootName: ROPE ← Rope.Concat["Msgset: ", msgSet];
lastReportFromPrinter ← NIL;
newPage ← UserProfile.Boolean[key: "Walnut.NewPageEveryMsg", default: FALSE];
smallHeaders ← UserProfile.Boolean[key: "Walnut.PrintSmallHeaders", default: TRUE];
BEGIN ENABLE
WalnutDefs.Error, IO.Error, UNWIND => printInfo.abortRef^ ← TRUE;
Report["Printing msgs from ", rootName];
msL ← WalnutOps.MsgsInSetEnumeration[msgSet, TRUE].mL;
TSExtras.PrintSuppliedNodes[nodeProc: SupplyMsg,
nameForSeparatorPage: rootName,
aborted: printInfo.abortRef,
messageProc: PrintReport ! TSTranslate.FontNotFound =>
{printInfo.abortRef^ ← TRUE; PrintReport[fontName];
PrintReport[" not found - aborting"]; CONTINUE}];
SignalPrintDone[printInfo];
END;  -- for UNWIND
};
PrintML: PROC [mL: LIST OF ROPE, name: ROPE, printInfo: PrintingInfo] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msg: ROPE;
firstMsg: BOOLTRUE;
firstCall: BOOLTRUE;
newPage, smallHeaders: BOOL;
SupplyMsg: TSExtras.NodeProc = {
IF firstCall THEN
{ node ← FirstNode[name];
firstCall ← FALSE;
RETURN
};
IF mL = NIL THEN RETURN[NIL];
msg ← mL.first;
mL ← mL.rest;
ReportProgress[firstMsg];
node ← FormatMsg[msg, firstMsg, newPage, smallHeaders];
firstMsg ← FALSE;
};
lastReportFromPrinter ← NIL;
newPage ← UserProfile.Boolean[key: "Walnut.NewPageEveryMsg", default: FALSE];
smallHeaders ← UserProfile.Boolean[key: "Walnut.PrintSmallHeaders", default: TRUE];
BEGIN ENABLE WalnutDefs.Error, IO.Error => {printInfo.abortRef^ ← TRUE};
TRUSTED
{ TSExtras.PrintSuppliedNodes[nodeProc: SupplyMsg,
nameForSeparatorPage: name,
aborted: printInfo.abortRef,
messageProc: PrintReport ! TSTranslate.FontNotFound =>
{printInfo.abortRef^ ← TRUE; PrintReport[fontName];
PrintReport[" not found - aborting"]; CONTINUE}]
};
SignalPrintDone[printInfo];
END;
};
ReportProgress: PROC[first: BOOL] =
{ IF first THEN ReportRope["\n."] ELSE ReportRope["."] };
PrintReport: PROC[r: ROPE] =
BEGIN
IF r = lastReportFromPrinter THEN RETURN;
ReportRope[lastReportFromPrinter ← r];
ReportRope["\n"];
END;
SignalPrintDone: ENTRY PROC[printInfo: PrintingInfo] =
BEGIN
printInfo.done ← TRUE;
BROADCAST PrintCallReturned;
END;
Failure: ENTRY PROC[printInfo: PrintingInfo, who: ROPE] =
BEGIN
Report[who, "; printing NOT done"];
printInfo.done ← TRUE;
printInfo.allOK ← FALSE;
BROADCAST PrintCallReturned;
END;
AbortPrintProc: PUBLIC ENTRY Menus.MenuProc =
BEGIN ENABLE UNWIND => NULL;
self: Viewer ← NARROW[parent];
printInfo: PrintingInfo ← NARROW[ViewerOps.FetchProp[self, $PrintingInfo]];
IF printInfo = NIL THEN RETURN;  -- perhaps an error??
IF printInfo.done THEN RETURN;   -- too late??
printInfo.abortRef^ ← TRUE;
IF self = walnut THEN
WalnutControlInternal.ChangeMenu[WalnutControlInternal.workingMenu, FALSE]
ELSE ViewerOps.SetMenu[self, blankMenu];
END;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
FirstNode: PROC[rootName: ROPE] RETURNS[node: TextNode.Ref] =
BEGIN
root: TiogaFileOps.Ref ← TiogaFileOps.CreateRoot[];
mark: ROPE = "outsideFooter";  -- kludge
prefix: ROPE = "(cedar) style (firstHeadersAfterPage) (0) .cvx .def";  -- magic
TRUSTED
{ TiogaOps.PutProp[LOOPHOLE[root], $Mark, mark];
TiogaOps.PutProp[LOOPHOLE[root], $Prefix, prefix];
};
TiogaFileOps.SetContents[root, rootName];
TRUSTED {node ← LOOPHOLE[root, TextNode.Ref]};
END;
FormatMsg: PROC[msg: ROPE, firstMsg, newPage, smallHeaders: BOOL]
RETURNS[node: TextNode.Ref] = {
contents: ViewerTools.TiogaContents ← WalnutOps.GetMsg[msg].contents;
endHeadersPos: INT ← Rope.Find[contents.contents, "\n\n"];
tocAndSubject: ROPE ← WalnutOps.GetDisplayProps[msg].TOCentry;
node ← PutGet.FromRope[Rope.Concat[contents.contents, contents.formatting]];
IF smallHeaders THEN IF endHeadersPos > 0 THEN
{ lastLoc: INT;
first: TiogaOps.Ref;
TRUSTED {first ← TiogaOps.FirstChild[LOOPHOLE[node]]};
lastLoc ← TiogaOps.LastLocWithin[first].where;
IF lastLoc > endHeadersPos THEN  -- no formatting already
{ looks: TextLooks.Looks ← TextLooks.noLooks;
looks['s] ← TRUE;
looks['p] ← TRUE;
TRUSTED {TextEdit.SetLooks[LOOPHOLE[node],
LOOPHOLE[first], looks, 0, endHeadersPos+1]};
};
};
IF tocAndSubject.Length[] > 75 THEN
tocAndSubject ← Rope.Concat[tocAndSubject.Substr[0, 70], " . . ."];
IF ~newPage THEN tocAndSubject ← Rope.Concat[lotaStars, tocAndSubject];
IF ~firstMsg THEN tocAndSubject ← Rope.Concat["\n\n", tocAndSubject];
TRUSTED
{ TiogaFileOps.SetContents[LOOPHOLE[node], tocAndSubject];
TiogaFileOps.SetFormat[LOOPHOLE[node], IF newPage THEN "head" ELSE "head2"]
};
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
start code
need an immediate menu button here, can't wait on walnutQueue
Menus.AppendMenuEntry[printingMenu, Menus.CreateEntry["AbortPrint", AbortPrintProc]];
END.