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
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: BOOL ← TRUE];
PrintingInfo: TYPE = REF PrintingInfoObject;
lastReportFromPrinter: ROPE ← NIL;
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[BOOL ← FALSE];
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[BOOL ← FALSE];
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[BOOL ← FALSE];
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[BOOL ← FALSE];
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];
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: BOOL ← TRUE;
firstMsg: BOOL ← TRUE;
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: BOOL ← TRUE;
firstCall: BOOL ← TRUE;
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.