<> <> <> <<>> <> <> <<[Cedar]TiogaImager>TiogaToInterpressImpl>> <> <> <> <> DIRECTORY Ascii USING [Digit, Letter], Atom USING [DottedPair, DottedPairNode, PropList, GetPName], Commander USING [CommandObject, Handle], CommandTool USING [AddSearchRule], FS, Imager USING [Context, metersPerPoint, ScaleT], ImagerInterpress USING [Ref, Create, Close, DoPage], ImagerPress USING [Close, NewPage, SimpleCreate], Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc], Install USING [Install], IO, List USING [PutAssoc], NodeProps USING [GetProp, PutProp], NodeStyleOps USING [defaultStyleName, Ref, Create], PeachPrint USING [PupAborted, DoPeachPrintCommand], PressPrinter USING [CurrentStateMessage, ProgressProc, SendPressFile], Process USING [Detach], ProcessProps USING [AddPropList], PutGet USING [FromRope, ToFile], RefText USING [AppendChar, ObtainScratch, ReleaseScratch], Rope, TextEdit USING [SetLooks], TextLooks USING [Looks, noLooks, RopeToLooks], TextNode USING [Location, Ref, LastChild, NarrowToTextNode, NewTextNode, StepForward], TiogaImager USING [FormattedPage, Destroy, FormatPage, Render], TiogaFileOps USING [CreateRoot, Ref, SetContents, SetFormat], TiogaOps USING [Ref, FirstChild, LastLocWithin, PutProp], TypeScript USING [Create], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, FetchProp, FindViewer, SetMenu], ViewerTools USING [TiogaContents], UserCredentials USING [Get], UserProfile USING [Boolean, Token], ViewerClasses USING [Viewer], WalnutDefs USING [Error], WalnutOps USING [MsgsInSetEnumeration, GetDisplayProps, GetMsg, MsgExists, SizeOfMsgSet], WalnutPrintOps USING [], WalnutControlInternal USING [ invocationDirectory, walnutMenu, workingMenu, ChangeMenu], WalnutWindowInternal USING [walnut, MsgSetButton, GetTSStream, Report, ReportRope]; WalnutPrintImpl: CEDAR MONITOR IMPORTS Ascii, Atom, CommandTool, FS, Imager, ImagerInterpress, ImagerPress, Install, IO, List, Menus, NodeProps, NodeStyleOps, PeachPrint, PressPrinter, Process, ProcessProps, RefText, Rope, UserProfile, UserCredentials, ViewerIO, ViewerOps, PutGet, TextEdit, TextLooks, TextNode, TiogaFileOps, TiogaImager, TiogaOps, TypeScript, WalnutDefs, WalnutOps, WalnutControlInternal, WalnutWindowInternal EXPORTS WalnutPrintOps = BEGIN OPEN WalnutWindowInternal; ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; STREAM: TYPE = IO.STREAM; blankMenu: PUBLIC Menus.Menu = Menus.CreateMenu[]; printingMenu: Menus.Menu _ Menus.CreateMenu[]; <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> NodeProc: TYPE = PROC RETURNS [node: TextNode.Ref]; PrintCallReturned: CONDITION; PrintingInfoObject: TYPE = RECORD[done: BOOL, abortRef: REF BOOL, allOK: BOOL _ TRUE]; PrintingInfo: TYPE = REF PrintingInfoObject; lastReportFromPrinter: ROPE _ NIL; defaultPrintName: ROPE = "///temp/WalnutPrint.press$"; ipDefaultPrintName: ROPE = "///temp/WalnutPrint.interpress"; cmdHandleForPrinting: Commander.Handle _ NIL; aNecessaryProperty: Atom.DottedPair = NEW[Atom.DottedPairNode _ [key: $WalnutPrintCommandHandle, val: NIL]]; <> MsgSetPrintProc: PUBLIC ENTRY PROC[viewer: Viewer, usePress: BOOL] = BEGIN ENABLE UNWIND => NULL; prevMenu: Menus.Menu _ viewer.menu; BEGIN ENABLE UNWIND => CONTINUE; aborted: REF BOOL = NEW[BOOL _ FALSE]; printInfo: PrintingInfo; msgSet: ROPE; IF ~CheckForPrinting[usePress: usePress] THEN RETURN; msgSet _ NARROW[ViewerOps.FetchProp[viewer, $WalnutMsgSetName]]; IF ~AnyMessages[msgSet] THEN RETURN; printInfo _ NEW[PrintingInfoObject _ [done: FALSE, abortRef: aborted]]; ViewerOps.AddProp[viewer, $PrintingInfo, printInfo]; viewer.inhibitDestroy _ TRUE; TRUSTED {Process.Detach[FORK PrintMSProc[msgSet, NIL, usePress, 1, printInfo]]}; ViewerOps.SetMenu[viewer, printingMenu]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; ViewerOps.SetMenu[viewer, prevMenu]; viewer.inhibitDestroy _ FALSE; END; MsgSetTOCPrintProc: PUBLIC ENTRY PROC[viewer: Viewer, usePress: BOOL] = BEGIN ENABLE UNWIND => NULL; prevMenu: Menus.Menu _ viewer.menu; BEGIN ENABLE UNWIND => CONTINUE; aborted: REF BOOL = NEW[BOOL _ FALSE]; printInfo: PrintingInfo; msgSet: ROPE; IF ~CheckForPrinting[usePress: usePress] THEN RETURN; msgSet _ NARROW[ViewerOps.FetchProp[viewer, $WalnutMsgSetName]]; IF ~AnyMessages[msgSet] THEN RETURN; printInfo _ NEW[PrintingInfoObject _ [done: FALSE, abortRef: aborted]]; ViewerOps.AddProp[viewer, $PrintingInfo, printInfo]; viewer.inhibitDestroy _ TRUE; TRUSTED {Process.Detach[FORK PrintMSTOCProc[msgSet, NIL, usePress, 1, printInfo]]}; ViewerOps.SetMenu[viewer, printingMenu]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; ViewerOps.SetMenu[viewer, prevMenu]; viewer.inhibitDestroy _ FALSE; END; MsgPrintProc: PUBLIC ENTRY PROC[viewer: Viewer, usePress: BOOL] = BEGIN ENABLE UNWIND => NULL; prevMenu: Menus.Menu _ viewer.menu; msg: ROPE = NARROW[ViewerOps.FetchProp[viewer, $WalnutMsgName]]; IF ViewerOps.FetchProp[viewer, $Frozen] # NIL AND ~WalnutOps.MsgExists[msg] THEN { WalnutWindowInternal.Report[ "Msg ", msg, " in a frozen viewer doesn't exist in this database"]; RETURN }; IF ~CheckForPrinting[usePress: usePress] THEN RETURN; BEGIN ENABLE UNWIND => CONTINUE; aborted: REF BOOL = NEW[BOOL _ FALSE]; printInfo: PrintingInfo; printInfo _ NEW[PrintingInfoObject _ [done: FALSE, abortRef: aborted]]; ViewerOps.AddProp[viewer, $PrintingInfo, printInfo]; viewer.inhibitDestroy _ TRUE; Report["Printing the msg: ", viewer.name]; TRUSTED {Process.Detach[FORK PrintML[LIST[msg], msg, NIL, usePress, 1, printInfo]]}; ViewerOps.SetMenu[viewer, printingMenu]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; ViewerOps.SetMenu[viewer, prevMenu]; viewer.inhibitDestroy _ FALSE; END; PrintMsgSetCmd: PUBLIC ENTRY PROC[msgSet, server: ROPE, usePress: BOOL, copies: INT] = { [] _ PrintMsgSetInternal[msgSet, server, usePress, copies] }; PrintMsgSet: PUBLIC ENTRY PROC[msgSet: ROPE, usePress: BOOL] RETURNS[allOK: BOOL] = { RETURN[PrintMsgSetInternal[msgSet, NIL, usePress, 1]] }; PrintMsgSetInternal: INTERNAL PROC[msgSet, server: ROPE, usePress: BOOL, copies: INT] RETURNS[allOK: BOOL] = BEGIN ENABLE UNWIND => NULL; printInfo: PrintingInfo; IF ~CheckForPrinting[usePress: usePress] 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, server, usePress, copies, printInfo]]}; WalnutControlInternal.ChangeMenu[printingMenu, TRUE]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; WalnutControlInternal.ChangeMenu[WalnutControlInternal.walnutMenu, FALSE]; walnut.inhibitDestroy _ FALSE; RETURN[printInfo.allOK]; END; PrintMsgSetTOCCmd: PUBLIC ENTRY PROC[msgSet, server: ROPE, usePress: BOOL, copies: INT] = { [] _ PrintMsgSetTOCInternal[msgSet, server, usePress, copies] }; PrintMsgSetTOC: PUBLIC ENTRY PROC[msgSet: ROPE, usePress: BOOL] RETURNS[allOK: BOOL] = { RETURN[PrintMsgSetTOCInternal[msgSet, NIL, usePress, 1]] }; PrintMsgSetTOCInternal: INTERNAL PROC[msgSet, server: ROPE, usePress: BOOL, copies: INT] RETURNS[allOK: BOOL] = BEGIN ENABLE UNWIND => NULL; printInfo: PrintingInfo; IF ~CheckForPrinting[usePress: usePress] 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 PrintMSTOCProc[msgSet, server, usePress, copies, printInfo]] }; WalnutControlInternal.ChangeMenu[printingMenu, TRUE]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; WalnutControlInternal.ChangeMenu[WalnutControlInternal.walnutMenu, FALSE]; walnut.inhibitDestroy _ FALSE; RETURN[printInfo.allOK]; END; PrintMsgCmd: PUBLIC ENTRY PROC[msg, server: ROPE, usePress: BOOL, copies: INT] = { ENABLE UNWIND => NULL; printInfo: PrintingInfo; IF ~CheckForPrinting[usePress: usePress] 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 PrintML[LIST[msg], msg, server, usePress, copies, printInfo]] }; WalnutControlInternal.ChangeMenu[printingMenu, TRUE]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; WalnutControlInternal.ChangeMenu[WalnutControlInternal.walnutMenu, FALSE]; walnut.inhibitDestroy _ FALSE; }; PrintMsgList: PUBLIC ENTRY PROC[ mList: LIST OF ROPE, msViewer: Viewer, server: ROPE _ NIL, usePress: BOOL _ TRUE, copies: INT _ 1] RETURNS[allOK: BOOL] = BEGIN ENABLE UNWIND => NULL; prevMenu: Menus.Menu _ msViewer.menu; printInfo: PrintingInfo; IF ~CheckForPrinting[usePress: usePress] 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 msg from ", msViewer.name]; TRUSTED { Process.Detach[ FORK PrintML[mList, msViewer.name, server, usePress, copies, printInfo]]; }; ViewerOps.SetMenu[msViewer, printingMenu]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; ViewerOps.SetMenu[msViewer, prevMenu]; msViewer.inhibitDestroy _ FALSE; RETURN[printInfo.allOK]; END; WriteMsgSets: PUBLIC ENTRY PROC[msgSetList: LIST OF MsgSetButton, fileName: ROPE] = { BEGIN ENABLE UNWIND => NULL; printInfo: PrintingInfo; 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 WriteMSProc[msgSetList, printInfo, fileName]]}; WalnutControlInternal.ChangeMenu[printingMenu, TRUE]; UNTIL printInfo.done DO WAIT PrintCallReturned; ENDLOOP; END; WalnutControlInternal.ChangeMenu[WalnutControlInternal.walnutMenu, FALSE]; walnut.inhibitDestroy _ FALSE; END; }; CheckForPrinting: INTERNAL PROC[usePress: BOOL] RETURNS[ok: BOOL] = BEGIN foundFile, failed: BOOL; Installit: PROC = { IF usePress THEN [foundFile, failed] _ Install.Install["WalnutPressPrint", cmdHandleForPrinting] ELSE [foundFile, failed] _ Install.Install["WalnutInterpressPrint", cmdHandleForPrinting]; }; IF cmdHandleForPrinting = NIL THEN { cmdHandleForPrinting _ NEW[Commander.CommandObject _ [propertyList: LIST[aNecessaryProperty]]]; cmdHandleForPrinting.in _ IO.noInputStream; cmdHandleForPrinting.err _ cmdHandleForPrinting.out _ WalnutWindowInternal.GetTSStream[]; CommandTool.AddSearchRule[ cmdHandleForPrinting, WalnutControlInternal.invocationDirectory]; CommandTool.AddSearchRule[cmdHandleForPrinting, "///Commands/"] }; ProcessProps.AddPropList[List.PutAssoc[key: $WorkingDirectory, val: WalnutControlInternal.invocationDirectory, aList: NIL], Installit]; IF ~foundFile THEN RETURN[FALSE]; IF failed THEN { Report["Couldn't run one of the files needed for printing - printing NOT done"]; 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"]; }; lotaStars: ROPE = "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"; <> <<>> PrintMSProc: PROC[msgSet, server: ROPE, usePress: BOOL, copies: INT, 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; 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[firstMsg]; node _ FormatMsg[msg _ msL.first, firstMsg, newPage, smallHeaders].node; 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: TextNode.Ref; IF ~useDefaultFile THEN fName _ Rope.Concat["///temp/Msgset-", msgSet ]; Report["Printing msgs from ", rootName]; msL _ WalnutOps.MsgsInSetEnumeration[msgSet, TRUE].mL; root _ BuildTiogaTree[SupplyMsg, printInfo.abortRef]; IF root # NIL THEN IF usePress THEN PressPrintRootNode[root, printInfo.abortRef, server, fName, copies] ELSE Interpress3PrintRootNode[root, printInfo.abortRef, server, fName, copies]; SignalPrintDone[printInfo]; END; -- for UNWIND }; WriteMSProc: PROC[ msgSetList: LIST OF MsgSetButton, printInfo: PrintingInfo, fileName: ROPE] = { ENABLE BEGIN WalnutDefs.Error => { Failure[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]; SupplyMsgs: NodeProc = { IF firstCall THEN { node _ FirstNode[fileName]; firstCall _ FALSE; RETURN }; IF msgList = NIL THEN { header: ROPE; IF msL = NIL THEN RETURN[NIL]; ReportRope["\n\t", header _ Rope.Concat["MessageSet: ", msL.first.msgSet.name]]; node _ PutGet.FromRope[""]; TRUSTED { TiogaFileOps.SetContents[LOOPHOLE[node], header]; TiogaFileOps.SetFormat[LOOPHOLE[node], "head2"] }; msgList _ WalnutOps.MsgsInSetEnumeration[msL.first.msgSet.name, TRUE].mL; msL _ msL.rest; firstMsg _ TRUE; RETURN }; ReportProgress[firstMsg]; node _ FormatMsg[msg _ msgList.first, firstMsg, FALSE, smallHeaders].node; msgList _ msgList.rest; firstMsg _ FALSE; }; Report["\nWriting MsgSets to file: ", fileName]; BEGIN ENABLE WalnutDefs.Error, IO.Error, UNWIND => printInfo.abortRef^ _ TRUE; root: TextNode.Ref; root _ BuildTiogaTree[SupplyMsgs, printInfo.abortRef]; IF root # NIL THEN [] _ PutGet.ToFile[fileName, root]; Report["\t ...done"]; SignalPrintDone[printInfo]; END; -- for UNWIND }; PrintMSTOCProc: PROC[ msgSet, server: ROPE, usePress: BOOL, copies: INT, 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; 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[firstMsg]; IF firstMsg THEN { looks: TextLooks.Looks _ TextLooks.noLooks; looks['b] _ TRUE; looks['l] _ TRUE; firstMsg _ FALSE; node _ PutGet.FromRope[Rope.Concat["* * * * * * * * TableOfContents from ", rootName]]; TRUSTED { first: TiogaOps.Ref _ TiogaOps.FirstChild[LOOPHOLE[node]]; TextEdit.SetLooks[LOOPHOLE[node], LOOPHOLE[first], looks]; }; } ELSE { node _ FormatTOC[msg _ msL.first]; msL _ msL.rest; }; }; FormatTOC: PROC[msg: ROPE] RETURNS[node: TextNode.Ref] = { hasBeenRead: BOOL; tocEntry: ROPE; looks: TextLooks.Looks _ TextLooks.noLooks; [hasBeenRead, tocEntry, ] _ WalnutOps.GetDisplayProps[msg]; tocEntry _ IF ~hasBeenRead AND needsQ THEN Rope.Concat["?", tocEntry] ELSE Rope.Concat[" ", tocEntry]; node _ PutGet.FromRope[tocEntry]; looks _ TextLooks.RopeToLooks[IF hasBeenRead THEN tocDefaultLooks ELSE tocUnreadLooks]; TRUSTED { first: TiogaOps.Ref _ TiogaOps.FirstChild[LOOPHOLE[node]]; TextEdit.SetLooks[LOOPHOLE[node], LOOPHOLE[first], looks]; }; }; rootName: ROPE _ Rope.Concat["Message Set: ", msgSet]; lastReportFromPrinter _ NIL; BEGIN ENABLE WalnutDefs.Error, IO.Error, UNWIND => printInfo.abortRef^ _ TRUE; fName: ROPE; root: TextNode.Ref; IF ~useDefaultFile THEN fName _ IO.PutFR["///temp/%g-TOC", IO.rope[msgSet] ]; Report["Printing Message TOCs from ", rootName]; msL _ WalnutOps.MsgsInSetEnumeration[msgSet, TRUE].mL; root _ BuildTiogaTree[SupplyTOC, printInfo.abortRef]; IF root # NIL THEN IF usePress THEN PressPrintRootNode[root, printInfo.abortRef, server, fName, copies] ELSE Interpress3PrintRootNode[root, printInfo.abortRef, server, fName, copies]; SignalPrintDone[printInfo]; END; -- for UNWIND }; PrintML: PROC [ mL: LIST OF ROPE, name, server: ROPE, usePress: BOOL, copies: INT, 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; 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[firstMsg]; node _ FormatMsg[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[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["///temp/", 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: TextNode.Ref = BuildTiogaTree[nodeProc: SupplyMsg, aborted: printInfo.abortRef]; IF root # NIL THEN IF usePress THEN PressPrintRootNode[root, printInfo.abortRef, server, fName, copies] ELSE Interpress3PrintRootNode[root, printInfo.abortRef, server, fName, copies]; SignalPrintDone[printInfo]; END; }; ReportProgress: PROC[first: BOOL] = { IF first THEN ReportRope["\t."] 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; <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> BuildTiogaTree: PROC[nodeProc: NodeProc, aborted: REF BOOL] RETURNS[TextNode.Ref] = { root, node: TextNode.Ref; prevLast: TextNode.Ref _ NIL; prop: REF; style: NodeStyleOps.Ref; IsAborted: PROC RETURNS [BOOL] = {RETURN[IF aborted = NIL THEN FALSE ELSE aborted^]}; InsertNode: PROC [root, node: TextNode.Ref, child: BOOL _ FALSE] = { <<-- if ~child then new is sibling of x>> <<-- else new is first child of x>> IF child THEN { IF root.child # NIL THEN { node.next _ root.child; node.last _ FALSE } ELSE { node.next _ root; node.last _ TRUE }; root.child _ node } ELSE { node.next _ root.next; node.last _ root.last; root.next _ node; root.last _ FALSE }; }; InsertAsLastChild: PROCEDURE [root, node, prevLast: TextNode.Ref] = { IF prevLast=NIL OR ~prevLast.last OR prevLast.next # root THEN prevLast _ TextNode.NarrowToTextNode[TextNode.LastChild[root]]; IF prevLast=NIL THEN InsertNode[root, node, TRUE] ELSE InsertNode[prevLast, node, FALSE]; }; <> root _ TextNode.NewTextNode[]; root.last _ TRUE; UNTIL ( node _ nodeProc[] ) = NIL DO IF IsAborted[] THEN RETURN[NIL]; InsertAsLastChild[root, node, prevLast]; prevLast _ node; <> style _ NodeStyleOps.Create[]; prop _ NodeProps.GetProp[node, $Prefix]; IF prop # NIL THEN NodeProps.PutProp[node, $Prefix, Rope.Cat[ NARROW[prop, Rope.ROPE], " \"", Atom.GetPName[NodeStyleOps.defaultStyleName], "\" style"]]; ENDLOOP; IF IsAborted[] THEN RETURN[NIL]; RETURN[root]; }; PressPrintRootNode: PROC[ root: TextNode.Ref, aborted: REF BOOL, server, fileName: ROPE, copies: INT] = { loc: TextNode.Location _ [node: TextNode.StepForward[root], where: 0]; pageCount: INT _ 0; marks: Atom.PropList _ NIL; fName: ROPE = IF fileName = NIL THEN defaultPrintName ELSE fileName.Concat[".press$"]; context: Imager.Context _ ImagerPress.SimpleCreate[fName]; IsAborted: PROC RETURNS [BOOL] = {RETURN[IF aborted = NIL THEN FALSE ELSE aborted^]}; WHILE loc.node # NIL DO page: TiogaImager.FormattedPage = TiogaImager.FormatPage[pageCounter: pageCount, startLoc: loc, marks: marks]; ImagerPress.NewPage[context]; Imager.ScaleT[context, Imager.metersPerPoint]; TiogaImager.Render[page.box, context, [0, 0]]; TiogaImager.Destroy[page.box]; loc _ page.nextLoc; IF IsAborted[] THEN EXIT; -- more or less clean state here pageCount _ pageCount + 1; marks _ page.marks; ENDLOOP; ImagerPress.Close[context]; IF IsAborted[] THEN RETURN; IF server.Length[] = 0 THEN server _ UserProfile.Token["Hardcopy.PressPrinter", "Clover"]; IF server.Equal["*"] THEN { Report[IO.PutFR["\nPress file (%g) written but not sent", IO.rope[fName] ]]; RETURN }; Report[ "\nForking a process to watch press printing - see WalnutPrinting typescript viewer"]; TRUSTED { Process.Detach[FORK PressPrinting[server, copies, fName]] }; }; Interpress3PrintRootNode: PROC[ root: TextNode.Ref, aborted: REF BOOL, server, fileName: ROPE, copies: INT] = { header: ROPE = "Interpress/Xerox/3.0 "; fName: ROPE = IF fileName = NIL THEN ipDefaultPrintName ELSE fileName.Concat[".interpress"]; master: ImagerInterpress.Ref = ImagerInterpress.Create[fName, header]; pageCount: INT _ 0; marks: Atom.PropList _ NIL; loc: TextNode.Location _ [node: TextNode.StepForward[root], where: 0]; IsAborted: PROC RETURNS [BOOL] = {RETURN[IF aborted = NIL THEN FALSE ELSE aborted^]}; 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]; IF IsAborted[] THEN RETURN; IF server.Length[] = 0 THEN server _ UserProfile.Token["Walnut.InterpressPrinter", "Quoth"]; IF server.Equal["*"] THEN { Report[IO.PutFR["\nInterPress file (%g) written but not sent", IO.rope[fName] ]]; RETURN }; Report[ "\nForking a process to watch interpress printing - see WalnutPrinting typescript viewer"]; TRUSTED { Process.Detach[FORK PeachPrinting[server, copies, fName]] }; }; walnutPrintTS: ROPE = "WalnutPrinting"; PressPrinting: PROC[server: ROPE, copies: INT, fName: ROPE] = { v: Viewer; out: STREAM; prgR: ROPE; openFile: FS.OpenFile; deleteAfterPrint: BOOL = UserProfile.Boolean["Walnut.DeleteFileAfterPrint", FALSE]; ProgressProc: PressPrinter.ProgressProc = { this: ROPE = handle.CurrentStateMessage[]; IF prgR # this THEN { out.PutRope[prgR _ this]; out.PutChar['\n]; }; }; [out, v] _ PrintingViewer["Press"]; IF deleteAfterPrint THEN openFile _ FS.Open[fName]; -- make sure doesn't go away [] _ PressPrinter.SendPressFile[ fileName: fName, server: server, progressProc: ProgressProc, copies: copies, userName: UserCredentials.Get[].name ]; IF deleteAfterPrint THEN { fullFName: ROPE = FS.GetName[openFile].fullFName; FS.Close[openFile]; FS.Delete[fullFName ! FS.Error => { out.PutRope[error.explanation]; out.PutChar['\n]; GOTO cant } ]; out.PutF[" Deleted press file %g\n", IO.rope[fName] ]; EXITS cant => NULL; }; v.inhibitDestroy _ FALSE; }; PeachPrinting: PROC[server: ROPE, copies: INT, fName: ROPE] = { out: STREAM; 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 PeachPrint.PupAborted => GOTO abt; [out, v] _ PrintingViewer["Interpress"]; PeachPrint.DoPeachPrintCommand[ server: server, file: fName, log: out, copies: copies ]; IF deleteAfterPrint THEN { fullFName: ROPE = FS.GetName[openFile].fullFName; FS.Close[openFile]; FS.Delete[fullFName ! FS.Error => { out.PutRope[error.explanation]; out.PutChar['\n]; GOTO cant } ]; out.PutF[" Deleted interpress file %g\n", IO.rope[fName] ]; EXITS cant => NULL; }; EXITS abt => out.PutRope["\nPupAborted from PeachPrint - quitting\n"]; END; v.inhibitDestroy _ FALSE; }; PrintingViewer: PROC[which: 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 at %g\n", IO.rope[which], IO.time[]]; }; <<>> <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> 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; [ , tocAndSubject, ] _ WalnutOps.GetDisplayProps[msg]; 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"] }; }; <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> <> <> Menus.AppendMenuEntry[printingMenu, Menus.CreateEntry["AbortPrint", AbortPrintProc]]; END.