WalnutPrintImpl.mesa
Copyright Ó 1985, 1986, 1987, 1988, 1989, 1992 by Xerox Corporation. All rights reserved.
Willie-sue, September 4, 1992 1:31 pm PDT
Doug Terry, January 8, 1992 11:31 am PST
Swinehar, October 22, 1991 10:31 pm PDT
Contents: Implementation of printing of Msgs, MsgSets, MsgSetTOC's (someday)
Taken from:
[Cedar]<CedarChest6.0>TiogaImager>TiogaToInterpressImpl
WalnutPrintImpl
Created by: Willie-Sue, June 29, 1983
Last edit by:
Willie-Sue on: December 27, 1984 2:45:23 pm PST
DIRECTORY
Ascii USING [Digit, Letter],
Atom USING [DottedPair, DottedPairNode, PropList],
BasicTime USING [Now],
Commander USING [CommandObject, Handle],
CommanderOps USING [DoCommand],
EditSpan,
FS,
Imager USING [Context, ScaleT],
ImagerInterpress USING [Ref, Create, Close, DoPage],
Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc],
IO,
List USING [PutAssoc],
PFS,
Process USING [Detach],
ProcessProps USING [AddPropList],
RefText USING [AppendChar, ObtainScratch, ReleaseScratch],
Rope,
TextEdit USING [ChangeLooks, ChangeStyle, FromRope, PutFormat, PutProp, ReplaceByRope],
TextLooks USING [Looks, noLooks, RopeToLooks],
TextNode USING [FirstChild, LastLocWithin, LastWithin, Location, MakeNodeLoc, MakeNodeSpan, NewTextNode, Root, StepForward],
Tioga USING [Location, Node, Place, Span],
TiogaImager USING [FormattedPage, Destroy, FormatPage, Render],
TiogaIO USING [FromPair, FromRope, ToFile],
TypeScript USING [Create],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [AddProp, FetchProp, FindViewer, SetMenu],
ViewerTools USING [TiogaContents],
UserProfile USING [Boolean, Token],
ViewerClasses USING [Viewer],
XNSPrint USING [Context, Error, GetDefaults, GetPrintRequestStatus, PrintFromFile, RequestStatus, StatusChangedProc],
WalnutDefs USING [Error],
WalnutOps USING [MsgsInSetEnumeration, GetDisplayProps, GetMsg, MsgExists, SizeOfMsgSet],
WalnutInternal USING [ blankMenu, invocationDirectory, ChangeMenu, HowToPrint, workingMenu],
WalnutWindow USING [Report, ReportFormat, ReportRope],
WalnutWindowPrivate USING [MsgAndHandle, MsgSetButton, MsgSetInfo, WalnutHandle, WalnutHandleRec];
WalnutPrintImpl:
CEDAR
MONITOR
IMPORTS
Ascii, BasicTime, CommanderOps, FS,
Imager, ImagerInterpress,
IO, List, Menus,
PFS, Process, ProcessProps, RefText, Rope,
UserProfile, ViewerIO, ViewerOps,
EditSpan, TextEdit, TextLooks, TextNode, TiogaImager, TiogaIO, TypeScript,
XNSPrint,
WalnutDefs, WalnutOps,
WalnutInternal, WalnutWindow
EXPORTS
WalnutInternal, WalnutWindow =
BEGIN OPEN WalnutInternal;
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
STREAM: TYPE = IO.STREAM;
HowToPrint: TYPE = WalnutInternal.HowToPrint;
MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton;
MsgAndHandle: TYPE = WalnutWindowPrivate.MsgAndHandle;
WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle;
WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec;
printingMenu: Menus.Menu ¬ Menus.CreateMenu[];
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NodeProc: TYPE = PROC RETURNS [node: Tioga.Node];
PrintCallReturned: CONDITION;
PrintingInfoRec:
TYPE =
RECORD[wH: WalnutHandle, done: BOOL, abortRef: REF BOOL, allOK: BOOL ¬ TRUE];
PrintingInfo: TYPE = REF PrintingInfoRec;
lastReportFromPrinter: ROPE ¬ NIL;
ipDefaultPrintName: ROPE = "/tmp/WalnutPrint.interpress";
cmdHandleForPrinting: Commander.Handle ¬ NIL;
aNecessaryProperty: Atom.DottedPair =
NEW[Atom.DottedPairNode ¬ [key: $WalnutPrintCommandHandle, val: NIL]];
prints msgset, using the msgset viewer
MsgSetPrintProc:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, viewer: Viewer, howToPrint: HowToPrint] = {
ENABLE
UNWIND =>
NULL;
prevMenu: Menus.Menu ¬ viewer.menu;
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo: PrintingInfo;
msI: WalnutWindowPrivate.MsgSetInfo;
msgSet: ROPE;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN;
msI ¬ NARROW[ViewerOps.FetchProp[viewer, $MsgSetInfo]];
IF msI = NIL THEN RETURN;
IF ~AnyMessages[wH, msgSet ¬ msI.button.msgSet.name] THEN RETURN;
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[viewer, $PrintingInfo, printInfo];
viewer.inhibitDestroy ¬ TRUE;
TRUSTED {Process.Detach[FORK PrintMSProc[wH, msgSet, NIL, howToPrint, 1, printInfo]]};
ViewerOps.SetMenu[viewer, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ViewerOps.SetMenu[viewer, prevMenu];
viewer.inhibitDestroy ¬ FALSE;
};
MsgSetTOCPrintProc:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, viewer: Viewer, howToPrint: HowToPrint] = {
ENABLE
UNWIND =>
NULL;
prevMenu: Menus.Menu ¬ viewer.menu;
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo: PrintingInfo;
msI: WalnutWindowPrivate.MsgSetInfo;
msgSet: ROPE;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN;
msI ¬ NARROW[ViewerOps.FetchProp[viewer, $MsgSetInfo]];
IF msI = NIL THEN RETURN;
IF ~AnyMessages[wH, msgSet ¬ msI.button.msgSet.name] THEN RETURN;
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[viewer, $PrintingInfo, printInfo];
viewer.inhibitDestroy ¬ TRUE;
TRUSTED
{Process.Detach[FORK PrintMSTOCProc[wH, msgSet, NIL, howToPrint, 1, printInfo]]};
ViewerOps.SetMenu[viewer, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ViewerOps.SetMenu[viewer, prevMenu];
viewer.inhibitDestroy ¬ FALSE;
};
MsgPrintProc:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, viewer: Viewer, howToPrint: HowToPrint] = {
ENABLE
UNWIND =>
NULL;
prevMenu: Menus.Menu ¬ viewer.menu;
msgAndWH: MsgAndHandle = NARROW[ViewerOps.FetchProp[viewer, $WalnutMsgName]];
IF ViewerOps.FetchProp[viewer, $Frozen] #
NIL
AND ~WalnutOps.MsgExists[wH.opsH, msgAndWH.msg]
THEN {
WalnutWindow.Report[wH,
"Msg ", msgAndWH.msg, " in a frozen viewer doesn't exist in this database"];
RETURN
};
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN;
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo: PrintingInfo;
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[viewer, $PrintingInfo, printInfo];
viewer.inhibitDestroy ¬ TRUE;
WalnutWindow.Report[wH, "Printing the msg: ", viewer.name];
TRUSTED {
Process.Detach[
FORK PrintML[wH, LIST[msgAndWH.msg], viewer.name, NIL, howToPrint, 1, printInfo]]
};
ViewerOps.SetMenu[viewer, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ViewerOps.SetMenu[viewer, prevMenu];
viewer.inhibitDestroy ¬ FALSE;
};
PrintMsgSetCmd:
PUBLIC
ENTRY
PROC[wH: WalnutHandle,
msgSet, server: ROPE, howToPrint: HowToPrint, copies: INT] =
{ [] ¬ PrintMsgSetInternal[wH, msgSet, server, howToPrint, copies] };
PrintMsgSet:
PUBLIC
ENTRY
PROC[wH: WalnutHandle,
msgSet: ROPE, howToPrint: HowToPrint] RETURNS[allOK: BOOL] =
{ RETURN[PrintMsgSetInternal[wH, msgSet, NIL, howToPrint, 1]] };
PrintMsgSetInternal:
INTERNAL
PROC[wH: WalnutHandle,
msgSet, server: ROPE, howToPrint: HowToPrint, copies: INT] RETURNS[allOK: BOOL] = {
ENABLE UNWIND => NULL;
printInfo: PrintingInfo;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN[FALSE];
IF ~AnyMessages[wH, msgSet] THEN RETURN[TRUE];
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[wH.walnut, $PrintingInfo, printInfo];
wH.walnut.inhibitDestroy ¬ TRUE;
TRUSTED
{Process.Detach[FORK PrintMSProc[wH, msgSet, server, howToPrint, copies, printInfo]]};
ChangeMenu[wH, printingMenu, TRUE];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ChangeMenu[wH, wH.walnutMenu, FALSE];
wH.walnut.inhibitDestroy ¬ FALSE;
RETURN[printInfo.allOK];
};
PrintMsgSetTOCCmd:
PUBLIC
ENTRY
PROC[wH: WalnutHandle,
msgSet, server: ROPE, howToPrint: HowToPrint, copies: INT] =
{ [] ¬ PrintMsgSetTOCInternal[wH, msgSet, server, howToPrint, copies] };
PrintMsgSetTOC:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, msgSet:
ROPE, howToPrint: HowToPrint]
RETURNS[allOK: BOOL] =
{ RETURN[PrintMsgSetTOCInternal[wH, msgSet, NIL, howToPrint, 1]] };
PrintMsgSetTOCInternal:
INTERNAL
PROC[wH: WalnutHandle, msgSet, server:
ROPE, howToPrint: HowToPrint, copies:
INT]
RETURNS[allOK: BOOL] = {
ENABLE UNWIND => NULL;
printInfo: PrintingInfo;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN[FALSE];
IF ~AnyMessages[wH, msgSet] THEN RETURN[TRUE];
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[wH.walnut, $PrintingInfo, printInfo];
wH.walnut.inhibitDestroy ¬ TRUE;
TRUSTED
{ Process.Detach[FORK PrintMSTOCProc[wH, msgSet, server, howToPrint, copies, printInfo]] };
ChangeMenu[wH, printingMenu, TRUE];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ChangeMenu[wH, wH.walnutMenu, FALSE];
wH.walnut.inhibitDestroy ¬ FALSE;
RETURN[printInfo.allOK];
};
PrintMsgCmd:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, msg, server:
ROPE, howToPrint: HowToPrint, copies:
INT] = {
ENABLE
UNWIND =>
NULL;
printInfo: PrintingInfo;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN;
BEGIN
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[wH.walnut, $PrintingInfo, printInfo];
wH.walnut.inhibitDestroy ¬ TRUE;
TRUSTED
{ Process.Detach[FORK PrintML[wH, LIST[msg], msg, server, howToPrint, copies, printInfo]] };
ChangeMenu[wH, printingMenu, TRUE];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
END;
ChangeMenu[wH, wH.walnutMenu, FALSE];
wH.walnut.inhibitDestroy ¬ FALSE;
PrintMsgList:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, mList:
LIST
OF
ROPE, msViewer: Viewer, server:
ROPE ¬
NIL, howToPrint: HowToPrint ¬ ip3, copies:
INT ¬ 1]
RETURNS[allOK: BOOL] = {
ENABLE
UNWIND =>
NULL;
prevMenu: Menus.Menu ¬ msViewer.menu;
printInfo: PrintingInfo;
IF ~CheckForPrinting[wH, howToPrint = press] THEN RETURN[FALSE];
IF mList = NIL THEN RETURN[TRUE];
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[msViewer, $PrintingInfo, printInfo];
msViewer.inhibitDestroy ¬ TRUE;
WalnutWindow.Report[wH, "Printing selected msg from ", msViewer.name];
TRUSTED { Process.Detach[
FORK PrintML[wH, mList, msViewer.name, server, howToPrint, copies, printInfo]];
};
ViewerOps.SetMenu[msViewer, printingMenu];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ViewerOps.SetMenu[msViewer, prevMenu];
msViewer.inhibitDestroy ¬ FALSE;
};
WriteMsgSets:
PUBLIC
ENTRY
PROC[wH: WalnutHandle, msgSetList:
LIST
OF MsgSetButton, tocsOnly:
BOOL, fileName:
ROPE] = {
ENABLE UNWIND => NULL;
printInfo: PrintingInfo;
{
ENABLE
UNWIND =>
CONTINUE;
aborted: REF BOOL = NEW[BOOL ¬ FALSE];
printInfo ¬ NEW[PrintingInfoRec ¬ [wH: wH, done: FALSE, abortRef: aborted]];
ViewerOps.AddProp[wH.walnut, $PrintingInfo, printInfo];
wH.walnut.inhibitDestroy ¬ TRUE;
TRUSTED
{ Process.Detach[FORK WriteMSProc[wH, msgSetList, printInfo, tocsOnly, fileName]] };
ChangeMenu[wH, printingMenu, TRUE];
UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP;
};
ChangeMenu[wH, wH.walnutMenu, FALSE];
wH.walnut.inhibitDestroy ¬ FALSE;
};
CheckForPrinting:
INTERNAL
PROC[wH: WalnutHandle, usePress:
BOOL]
RETURNS[ok: BOOL] = {
res: REF;
Installit:
PROC = {
res ¬ CommanderOps.DoCommand["Install WalnutInterpressPrint", cmdHandleForPrinting];
};
IF usePress THEN RETURN[FALSE];
IF cmdHandleForPrinting =
NIL
THEN {
cmdHandleForPrinting ¬
NEW[Commander.CommandObject ¬ [propertyList: LIST[aNecessaryProperty]]];
cmdHandleForPrinting.in ¬ IO.noInputStream;
};
always get the current walnut typescript stream
cmdHandleForPrinting.err ¬ cmdHandleForPrinting.out ¬ wH.wtsOut;
ProcessProps.AddPropList[List.PutAssoc[key: $WorkingDirectory, val: invocationDirectory, aList: NIL], Installit];
IF res = $Failure THEN RETURN[FALSE];
IF failed THEN {
WalnutWindow.Report[
wH, "Couldn't run one of the files needed for printing - printing NOT done"];
RETURN[FALSE];
};
RETURN[TRUE];
};
AnyMessages:
PROC[wH: WalnutHandle, msgSet:
ROPE]
RETURNS[any:
BOOL] = {
IF any ¬ (WalnutOps.SizeOfMsgSet[wH.opsH, msgSet].messages # 0) THEN RETURN;
WalnutWindow.ReportFormat[wH, "Msgset: %g contains no msgs", [rope[msgSet]] ];
};
lotaStars: ROPE = "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r";
prints msgSet
PrintMSProc:
PROC[wH: WalnutHandle, msgSet, server:
ROPE, howToPrint: HowToPrint, copies:
INT, printInfo: PrintingInfo] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[wH, printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msL: LIST OF ROPE;
msg: ROPE;
firstCall: BOOL ¬ TRUE;
firstMsg: BOOL ¬ TRUE;
newPage, smallHeaders: BOOL;
useDefaultFile: BOOL = UserProfile.Boolean[key: "Walnut.UseDefaultPrintFile", default: TRUE];
SupplyMsg: NodeProc = {
IF firstCall
THEN
{ node ¬ FirstNode[rootName];
firstCall ¬ FALSE;
RETURN
};
IF msL = NIL THEN RETURN[NIL];
ReportProgress[wH, firstMsg];
node ¬ FormatMsg[wH, msg ¬ msL.first, firstMsg, newPage, smallHeaders];
msL ¬ msL.rest;
firstMsg ¬ FALSE;
};
rootName: ROPE ¬ Rope.Concat["Message Set: ", 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;
fName: ROPE;
root: Tioga.Node;
IF ~useDefaultFile THEN fName ¬ Rope.Concat["/tmp/Msgset-", msgSet ];
WalnutWindow.Report[wH, "Printing msgs from ", rootName];
msL ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, msgSet, TRUE].mL;
root ¬ BuildTiogaTree[SupplyMsg, printInfo.abortRef, howToPrint];
IF root #
NIL
THEN
InterpressPrintRootNode[wH, root, printInfo.abortRef, server, fName, howToPrint, copies];
SignalPrintDone[printInfo];
END; -- for UNWIND
};
WriteMSProc:
PROC[wH: WalnutHandle, msgSetList:
LIST
OF MsgSetButton, printInfo: PrintingInfo, tocsOnly:
BOOL, fileName:
ROPE] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[wH, printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msL: LIST OF MsgSetButton ¬ msgSetList;
msgList: LIST OF ROPE;
msg: ROPE;
firstCall: BOOL ¬ TRUE;
firstMsg: BOOL ¬ TRUE;
smallHeaders: BOOL = UserProfile.Boolean[key: "Walnut.PrintSmallHeaders", default: TRUE];
tocDefaultLooks: ROPE = UserProfile.Token[key: "Walnut.TOCDefaultLooks", default: ""];
tocUnreadLooks: ROPE = UserProfile.Token[key: "Walnut.TOCUnreadLooks", default: "i"];
userWantsQMs: BOOL = UserProfile.Boolean[key: "Walnut.ShowUnreadWithQMs", default: TRUE];
needsQ: BOOL = userWantsQMs OR (tocUnreadLooks = NIL);
SupplyMsgs: NodeProc = {
IF firstCall
THEN
{ node ¬ FirstNode[fileName];
firstCall ¬ FALSE;
RETURN
};
IF msgList =
NIL
THEN {
header: ROPE;
IF msL = NIL THEN RETURN[NIL];
WalnutWindow.ReportRope[wH,
"\n\t", header ¬ Rope.Concat["MessageSet: ", msL.first.msgSet.name]];
node ¬ TextNode.NewTextNode[];
[] ¬ TextEdit.ReplaceByRope[root: node, dest: node, rope: header];
TextEdit.PutFormat[node, $head2];
msgList ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, msL.first.msgSet.name, TRUE].mL;
msL ¬ msL.rest;
firstMsg ¬ TRUE;
RETURN
};
ReportProgress[wH, firstMsg];
node ¬ FormatMsg[wH, msg ¬ msgList.first, firstMsg, FALSE, smallHeaders];
msgList ¬ msgList.rest;
firstMsg ¬ FALSE;
};
SupplyTOC: NodeProc = {
IF firstCall
THEN {
node ¬ FirstNode[fileName];
firstCall ¬ FALSE;
RETURN
};
IF msgList =
NIL
THEN {
looks: TextLooks.Looks ¬ TextLooks.noLooks;
IF msL = NIL THEN RETURN[NIL];
WalnutWindow.ReportRope[wH,
"\n\t", Rope.Concat["TOCs from MessageSet: ", msL.first.msgSet.name]];
looks['b] ¬ TRUE;
looks['l] ¬ TRUE;
firstMsg ¬ FALSE;
node ¬
TiogaIO.FromRope[Rope.Concat["\r\r* * * * * * * * TableOfContents from ", msL.first.msgSet.name]];
TextEdit.ChangeLooks[root: node, text: TextNode.FirstChild[node], add: looks];
msgList ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, msL.first.msgSet.name, TRUE].mL;
msL ¬ msL.rest;
firstMsg ¬ TRUE;
RETURN
};
ReportProgress[wH, firstMsg];
node ¬ FormatTOC[wH, msg ¬ msgList.first, needsQ, tocDefaultLooks, tocUnreadLooks];
msgList ¬ msgList.rest;
firstMsg ¬ FALSE;
};
IF tocsOnly
THEN
WalnutWindow.Report[wH, "\nWriting MsgSet TOCs to file: ", fileName]
ELSE WalnutWindow.Report[wH, "\nWriting MsgSets to file: ", fileName];
BEGIN
ENABLE
WalnutDefs.Error, IO.Error, UNWIND => printInfo.abortRef ¬ TRUE;
root: Tioga.Node;
IF tocsOnly
THEN root ¬ BuildTiogaTree[SupplyTOC, printInfo.abortRef, ip3]
ELSE root ¬ BuildTiogaTree[SupplyMsgs, printInfo.abortRef, ip3];
IF root # NIL THEN [] ¬ TiogaIO.ToFile[PFS.PathFromRope[fileName], root];
WalnutWindow.Report[wH, "\t ...done"];
SignalPrintDone[printInfo];
END; -- for UNWIND
};
PrintMSTOCProc:
PROC[wH: WalnutHandle, msgSet, server:
ROPE, howToPrint: HowToPrint, copies:
INT, printInfo: PrintingInfo] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[wH, printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msL: LIST OF ROPE;
msg: ROPE;
firstCall: BOOL ¬ TRUE;
firstMsg: BOOL ¬ TRUE;
tocDefaultLooks: ROPE = UserProfile.Token[key: "Walnut.TOCDefaultLooks", default: ""];
tocUnreadLooks: ROPE = UserProfile.Token[key: "Walnut.TOCUnreadLooks", default: "i"];
userWantsQMs: BOOL = UserProfile.Boolean[key: "Walnut.ShowUnreadWithQMs", default: TRUE];
useDefaultFile: BOOL = UserProfile.Boolean[key: "Walnut.UseDefaultPrintFile", default: TRUE];
needsQ: BOOL = userWantsQMs OR (tocUnreadLooks = NIL);
SupplyTOC: NodeProc = {
IF firstCall
THEN {
node ¬ FirstNode[rootName];
firstCall ¬ FALSE;
RETURN
};
IF msL = NIL THEN RETURN[NIL];
ReportProgress[wH, firstMsg];
IF firstMsg
THEN {
looks: TextLooks.Looks ¬ TextLooks.noLooks;
looks['b] ¬ TRUE;
looks['l] ¬ TRUE;
firstMsg ¬ FALSE;
node ¬
TiogaIO.FromRope[Rope.Concat["* * * * * * * * TableOfContents from ", rootName]];
TextEdit.ChangeLooks[root: node, text: TextNode.FirstChild[node], add: looks];
}
ELSE {
node ¬ FormatTOC[wH, msg ¬ msL.first, needsQ, tocDefaultLooks, tocUnreadLooks];
msL ¬ msL.rest;
};
};
rootName: ROPE ¬ Rope.Concat["Message Set: ", msgSet];
lastReportFromPrinter ¬ NIL;
BEGIN
ENABLE
WalnutDefs.Error, IO.Error, UNWIND => printInfo.abortRef ¬ TRUE;
fName: ROPE;
root: Tioga.Node;
IF ~useDefaultFile THEN fName ¬ IO.PutFR1["/tmp/%g-TOC", [rope[msgSet]] ];
WalnutWindow.Report[wH, "Printing Message TOCs from ", rootName];
msL ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, msgSet, TRUE].mL;
root ¬ BuildTiogaTree[SupplyTOC, printInfo.abortRef, howToPrint];
IF root #
NIL
THEN
InterpressPrintRootNode[wH, root, printInfo.abortRef, server, fName, howToPrint, copies];
SignalPrintDone[printInfo];
END; -- for UNWIND
};
PrintML:
PROC [wH: WalnutHandle, mL:
LIST
OF
ROPE, name, server:
ROPE, howToPrint: HowToPrint, copies:
INT, printInfo: PrintingInfo] = {
ENABLE BEGIN
WalnutDefs.Error => { Failure[wH, printInfo, explanation]; CONTINUE};
UNWIND => SignalPrintDone[printInfo];
END;
msg: ROPE;
firstMsg: BOOL ¬ TRUE;
firstCall: BOOL ¬ TRUE;
newPage, smallHeaders: BOOL;
useDefaultFile: BOOL = UserProfile.Boolean[key: "Walnut.UseDefaultPrintFile", default: TRUE];
fName: ROPE;
SupplyMsg: NodeProc = {
IF firstCall
THEN
{ node ¬ FirstNode[name];
firstCall ¬ FALSE;
RETURN
};
IF mL = NIL THEN RETURN;
msg ¬ mL.first;
mL ¬ mL.rest;
ReportProgress[wH, firstMsg];
node ¬ FormatMsg[wH, msg, firstMsg, newPage, smallHeaders];
firstMsg ¬ FALSE;
};
IF ~useDefaultFile
THEN
BEGIN
msg: ROPE = mL.first;
tocAndSubject, subject: ROPE;
startOfSubject: INT;
rt: REF TEXT ¬ RefText.ObtainScratch[20];
len: INT ¬ 0;
[ , tocAndSubject, startOfSubject] ¬ WalnutOps.GetDisplayProps[wH.opsH, msg];
subject ¬ tocAndSubject.Substr[startOfSubject];
FOR i:
INT
IN [0..subject.Length[])
DO
c: CHAR = subject.Fetch[i];
IF ~(Ascii.Letter[c] OR Ascii.Digit[c]) THEN LOOP;
rt ¬ RefText.AppendChar[rt, c];
IF (len ¬ len + 1) >= 20 THEN EXIT;
ENDLOOP;
fName ¬ Rope.Concat["/tmp/", Rope.FromRefText[rt] ];
RefText.ReleaseScratch[rt];
END;
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};
root: Tioga.Node =
BuildTiogaTree[SupplyMsg, printInfo.abortRef, howToPrint];
IF root #
NIL
THEN
InterpressPrintRootNode[wH, root, printInfo.abortRef, server, fName, howToPrint, copies];
SignalPrintDone[printInfo];
END;
};
ReportProgress:
PROC[wH: WalnutHandle, first:
BOOL] = {
IF first THEN WalnutWindow.ReportRope[wH, "\t."] ELSE WalnutWindow.ReportRope[wH, "."];
};
PrintReport:
PROC[wH: WalnutHandle, r:
ROPE] = {
IF r = lastReportFromPrinter THEN RETURN;
WalnutWindow.ReportRope[wH, lastReportFromPrinter ¬ r];
WalnutWindow.ReportRope[wH, "\n"];
};
SignalPrintDone:
ENTRY
PROC[printInfo: PrintingInfo] = {
printInfo.done ¬ TRUE;
BROADCAST PrintCallReturned;
};
Failure:
ENTRY
PROC[wH: WalnutHandle, printInfo: PrintingInfo, who:
ROPE] = {
WalnutWindow.Report[wH, who, "; printing NOT done"];
printInfo.done ¬ TRUE;
printInfo.allOK ¬ FALSE;
BROADCAST PrintCallReturned;
};
AbortPrintProc:
PUBLIC
ENTRY Menus.MenuProc = {
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 = printInfo.wH.walnut
THEN ChangeMenu[printInfo.wH, workingMenu,
FALSE]
ELSE ViewerOps.SetMenu[self, blankMenu];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildTiogaTree:
PROC[nodeProc: NodeProc, aborted:
REF
BOOL, howToPrint: HowToPrint]
RETURNS[Tioga.Node] = {
root, node: Tioga.Node;
prev: Tioga.Node ¬ NIL;
IsAborted: PROC RETURNS [BOOL] = {RETURN[IF aborted = NIL THEN FALSE ELSE aborted]};
build a tree with the supplied nodes
where: Tioga.Place ¬ child;
prev ¬ root ¬ TextNode.NewTextNode[];
UNTIL ( node ¬ nodeProc[] ) =
NIL
DO
new: Tioga.Node;
IF IsAborted[] THEN RETURN[NIL];
new ¬ InsertNode[prev, node, where];
where ¬ sibling; -- child just the first time
prev ¬ new;
ENDLOOP;
TextEdit.ChangeStyle[node: root, name: "cedar"]; -- set root style
IF IsAborted[] THEN RETURN[NIL];
RETURN[root];
};
InsertNode:
PROC [prev, node: Tioga.Node, where: Tioga.Place]
RETURNS[new: Tioga.Node] = {
node may have children, but no siblings
destLoc: Tioga.Location ~ TextNode.MakeNodeLoc[prev];
sourceSpan: Tioga.Span ~ TextNode.MakeNodeSpan[node, TextNode.LastWithin[node]];
resSpan: Tioga.Span ¬ EditSpan.Copy[
destRoot: TextNode.Root[prev], sourceRoot: TextNode.Root[node],
dest: destLoc, source: sourceSpan, where: where];
new ¬ resSpan.start.node;
};
InterpressPrintRootNode:
PROC[wH: WalnutHandle, root: Tioga.Node, aborted:
REF
BOOL, server, fileName:
ROPE, howToPrint: HowToPrint, copies:
INT] = {
IsAborted: PROC RETURNS [BOOL] = {RETURN[IF aborted = NIL THEN FALSE ELSE aborted]};
header: ROPE = IF howToPrint = ip2 THEN "Interpress/Xerox/2.0 " ELSE "Interpress/Xerox/3.0 ";
fName:
ROPE =
IF fileName = NIL THEN ipDefaultPrintName ELSE fileName.Concat[".interpress"];
tName: ROPE ~ fileName.Concat[".tioga"];
master: ImagerInterpress.Ref = ImagerInterpress.Create[fName, header];
pageCount: INT ¬ 0;
marks: Atom.PropList ¬ NIL;
loc: TextNode.Location ¬ [node: TextNode.StepForward[root], where: 0];
WHILE loc.node #
NIL
DO
page: TiogaImager.FormattedPage;
paint:
PROC [context: Imager.Context] = {
Imager.ScaleT[context, 0.0254/72.27];
TiogaImager.Render[page.box, context, [0, 0]];
};
page ¬ TiogaImager.FormatPage[
pageCounter: pageCount, startLoc: loc, filter: NIL, marks: marks];
ImagerInterpress.DoPage[master, paint];
TiogaImager.Destroy[page.box];
pageCount ¬ pageCount + 1;
marks ¬ page.marks;
loc ¬ page.nextLoc;
ENDLOOP;
ImagerInterpress.Close[master];
[] ¬ TiogaIO.ToFile[PFS.PathFromRope[tName], root]; -- debugging
IF IsAborted[] THEN RETURN;
IF server.Length[] = 0
THEN
server ¬ UserProfile.Token["Hardcopy.InterpressPrinter", "Snoball"];
IF server.Equal["*"]
THEN {
WalnutWindow.ReportFormat[wH, "\nInterPress%g file (%g) written but not sent\n",
[rope[IF howToPrint = ip2 THEN "2.0" ELSE "3.0"]], [rope[fName]] ];
RETURN
};
WalnutWindow.Report[wH,
"\nForking a process to watch interpress printing - see WalnutPrinting typescript viewer"];
TRUSTED { Process.Detach[FORK InterpressPrinting[server, copies, fName]] };
};
walnutPrintTS: ROPE = "WalnutPrinting";
ipPrintingContext: XNSPrint.Context ¬ NIL;
ipPrintViewerOut: STREAM;
InterpressPrinting:
PROC[server:
ROPE, copies:
INT, fName:
ROPE] = {
v: ViewerClasses.Viewer;
openFile: FS.OpenFile;
deleteAfterPrint: BOOL = UserProfile.Boolean["Walnut.DeleteFileAfterPrint", FALSE];
IF deleteAfterPrint THEN openFile ¬ FS.Open[fName]; -- make sure doesn't go away
BEGIN
ENABLE XNSPrint.Error => {
ipPrintViewerOut.PutF1["\n**** Error from XNSPrint, explanation is: %g\nquitting\n",
[rope[explanation]] ];
GOTO err;
};
[ipPrintViewerOut, v] ¬ PrintingViewer["Interpress", fName];
ipPrintingContext ¬ XNSPrint.GetDefaults[ipPrintingContext];
IF server.Length[] # 0 THEN ipPrintingContext.printerName ¬ server;
ipPrintingContext.copyCount ¬ copies;
[] ¬ XNSPrint.PrintFromFile[
file: fName,
context: ipPrintingContext
update: WatchInterpressPrinting
];
ipPrintViewerOut.PutF1["File has been sent to %g\n", [rope[ipPrintingContext.printerName]] ];
IF deleteAfterPrint
THEN {
fullFName: ROPE = FS.GetName[openFile].fullFName;
FS.Close[openFile];
FS.Delete[fullFName
!
FS.Error => {
ipPrintViewerOut.PutRope[error.explanation];
ipPrintViewerOut.PutChar['\n];
GOTO cant } ];
ipPrintViewerOut.PutF1[" Deleted interpress file %g\n", [rope[fName]] ];
};
END;
v.inhibitDestroy ¬ FALSE;
};
WatchInterpressPrinting: XNSPrint.StatusChangedProc = {
status: XNSPrint.RequestStatus = XNSPrint.GetPrintRequestStatus[request];
BEGIN
ENABLE
IO.Error =>
GOTO ignore;
ipPrintViewerOut.PutRope[status.statusMessage];
ipPrintViewerOut.PutChar['\n];
EXITS ignore => NULL;
END;
};
PrintingViewer:
PROC[which, fName:
ROPE]
RETURNS[out:
STREAM, v: Viewer] = {
v ¬ ViewerOps.FindViewer[walnutPrintTS];
IF v =
NIL
THEN
v ¬ TypeScript.Create[
info: [name: walnutPrintTS, iconic: TRUE, column: left, openHeight: 78],
paint: TRUE];
v.inhibitDestroy ¬ TRUE;
out ¬ ViewerIO.CreateViewerStreams[name: NIL, viewer: v].out;
out.PutF["\n*****Start sending (%g) file \"%g\" at %g\n",
[rope[which]], [rope[fName]], [time[BasicTime.Now[]]] ];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
FirstNode:
PROC[rootName:
ROPE]
RETURNS[node: Tioga.Node] = {
node ¬ TextEdit.FromRope[rootName];
TextEdit.PutProp[node, $Mark, Rope.Literal["outsideFooter"]];
};
FormatMsg:
PROC[wH: WalnutHandle, msg:
ROPE, firstMsg, newPage, smallHeaders:
BOOL]
RETURNS[Tioga.Node] = {
tocRoot, toc, body: Tioga.Node;
contents: ViewerTools.TiogaContents ~ WalnutOps.GetMsg[wH.opsH, msg].contents;
tocAndSubject: ROPE ¬ WalnutOps.GetDisplayProps[wH.opsH, msg].tocEntry;
endHeadersPos: INT ¬ Rope.Find[contents.contents, "\n\n"];
IF endHeadersPos < 0 THEN endHeadersPos ¬ Rope.Find[contents.contents, "\r\r"];
body ¬ TiogaIO.FromPair[[contents: contents.contents, formatting: contents.formatting]];
IF smallHeaders
AND ( endHeadersPos > 0 )
THEN {
first: Tioga.Node ¬ TextNode.FirstChild[body];
lastLoc: INT ~ TextNode.LastLocWithin[first].where;
IF lastLoc > endHeadersPos
THEN
-- no formatting already
{ looks: TextLooks.Looks ¬ TextLooks.noLooks;
looks['s] ¬ TRUE;
looks['p] ¬ TRUE;
TextEdit.ChangeLooks[root: body, text: first, add: looks, start: 0, len: 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["\r\r", tocAndSubject];
toc ¬ TextNode.FirstChild[tocRoot ¬ TiogaIO.FromRope[tocAndSubject]];
TextEdit.PutFormat[toc, IF newPage THEN $head ELSE $head2];
[] ¬ InsertNode[toc, body, child];
RETURN[tocRoot];
FormatTOC:
PROC[wH: WalnutHandle, msg:
ROPE, needsQ:
BOOL, tocDefaultLooks, tocUnreadLooks:
ROPE]
RETURNS[Tioga.Node] = {
node: Tioga.Node;
hasBeenRead: BOOL;
tocEntry: ROPE;
looks: TextLooks.Looks ¬ TextLooks.noLooks;
[hasBeenRead, tocEntry, ] ¬ WalnutOps.GetDisplayProps[wH.opsH, msg];
tocEntry ¬
IF ~hasBeenRead
AND needsQ
THEN Rope.Concat["?", tocEntry]
ELSE Rope.Concat[" ", tocEntry];
node ¬ TiogaIO.FromRope[tocEntry];
looks ¬ TextLooks.RopeToLooks[IF hasBeenRead THEN tocDefaultLooks ELSE tocUnreadLooks];
TextEdit.ChangeLooks[root: node, text: TextNode.FirstChild[node], add: looks];
RETURN[node];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
start code
need an immediate menu button here, can't wait on walnutQueue
Menus.AppendMenuEntry[printingMenu, Menus.CreateEntry["AbortPrint", AbortPrintProc]];
END.