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]]; 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; RETURN[printInfo.allOK]; }; 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; }; cmdHandleForPrinting.err ¬ cmdHandleForPrinting.out ¬ wH.wtsOut; ProcessProps.AddPropList[List.PutAssoc[key: $WorkingDirectory, val: invocationDirectory, aList: NIL], Installit]; IF res = $Failure THEN 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"; 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­]}; 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] = { 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"]; 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]; 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 ]; 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]] ]; EXITS cant => NULL; }; EXITS err => NULL; 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]; }; Menus.AppendMenuEntry[printingMenu, Menus.CreateEntry["AbortPrint", AbortPrintProc]]; END. > 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]TiogaImager>TiogaToInterpressImpl WalnutPrintImpl Created by: Willie-Sue, June 29, 1983 Last edit by: Willie-Sue on: December 27, 1984 2:45:23 pm PST * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * prints msgset, using the msgset viewer always get the current walnut typescript stream IF failed THEN { WalnutWindow.Report[ wH, "Couldn't run one of the files needed for printing - printing NOT done"]; RETURN[FALSE]; }; prints msgSet * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * build a tree with the supplied nodes node may have children, but no siblings tName: ROPE ~ fileName.Concat[".tioga"]; [] ¬ TiogaIO.ToFile[PFS.PathFromRope[tName], root]; -- debugging update: WatchInterpressPrinting * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * start code need an immediate menu button here, can't wait on walnutQueue Κφ•NewlineDelimiter –(cedarcode) style™codešΟn™Kšœ ΟeœO™ZK™)K™(K™'K™KšœL™LKšœ ™ Kšœ7™7K™Kšœ%™%—K˜šœ ™ Kšœ/™/K˜—šΟk ˜ KšœŸœ˜KšœŸœ(˜2Kšœ Ÿœ˜Kšœ Ÿœ˜(Kšœ Ÿœ ˜K˜ KšŸœ˜KšœŸœ˜KšœŸœ˜4KšœŸœ<˜GKšŸœ˜KšœŸœ ˜KšŸœ˜KšœŸœ ˜Kšœ Ÿœ˜!KšœŸœ-˜:K˜Kšœ ŸœI˜WKšœ Ÿœ˜.Kšœ Ÿœn˜|KšœŸœ˜*Kšœ Ÿœ.˜?KšœŸœ˜+Kšœ Ÿœ ˜Kšœ Ÿœ˜%Kšœ Ÿœ+˜:Kšœ Ÿœ˜"Kšœ Ÿœ˜#KšœŸœ ˜Kšœ Ÿœg˜uK˜Kšœ Ÿœ ˜Kšœ ŸœJ˜YK˜KšœŸœH˜\Kšœ Ÿœ$˜6KšœŸœI˜bK˜—šœŸœŸ˜šŸ˜Kšœ Ÿœ˜#Kšœ˜KšŸœ˜KšŸœ'˜*Kšœ!˜!K˜JK˜ K˜Kšœ˜—šŸ˜Kšœ˜K˜——KšŸœŸœ˜K˜KšŸœŸœŸœ˜KšœŸœ˜$KšŸœŸœŸœŸœ˜Kšœ Ÿœ˜-K˜KšœŸœ$˜6KšœŸœ$˜6KšœŸœ$˜6KšœŸ œ'˜CK˜K˜.K˜KšœM™MKšœ ŸœŸœŸœ˜1K˜KšœŸ œ˜šœŸœ˜Kš ŸœŸœ ŸœŸœ ŸœŸœ˜M—KšœŸœŸœ˜)KšœŸœŸœ˜"K˜KšœŸœ!˜9Kšœ)Ÿœ˜-šœ%˜%KšŸœ=Ÿœ˜F—K˜Kšœ&™&K˜šœŸœŸœŸœ>˜`šŸœŸœŸœ˜K˜#K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&K˜Kšœ$˜$KšœŸœ˜ KšŸœ+ŸœŸœ˜9KšœŸœ+˜7KšŸœŸœŸœŸœ˜KšŸœ3ŸœŸœ˜AK˜Kšœ Ÿœ"Ÿœ˜LKšœ4˜4KšœŸœ˜KšŸœŸœŸœ˜VKšœ(˜(KšŸœŸœŸœŸœ˜8Kšœ˜—K˜Kšœ$˜$KšœŸœ˜—Kšœ˜—K˜šœŸœŸœŸœ>˜cšŸœŸœŸœ˜K˜#K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&K˜Kšœ$˜$KšœŸœ˜ KšŸœ+ŸœŸœ˜9KšœŸœ+˜7KšŸœŸœŸœŸœ˜KšŸœ3ŸœŸœ˜AK˜Kšœ Ÿœ"Ÿœ˜LKšœ4˜4KšœŸœ˜šŸ˜KšœŸœŸœ˜Q—Kšœ(˜(KšŸœŸœŸœŸœ˜8Kšœ˜—K˜Kšœ$˜$KšœŸœ˜—Kšœ˜—K˜š œŸœŸœŸœ>˜]šŸœŸœŸœ˜K˜#KšœŸœ.˜MšŸœ(ŸœŸœ-Ÿœ˜d˜KšœL˜L—KšŸ˜K˜—K˜KšŸœ+ŸœŸœ˜9K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&K˜Kšœ Ÿœ"Ÿœ˜LK˜4KšœŸœ˜Kšœ;˜;šŸœ˜ šœ˜KšŸœ ŸœŸœ˜Q—Kšœ˜—Kšœ(˜(KšŸœŸœŸœŸœ˜8Kšœ˜—K˜Kšœ$˜$KšœŸœ˜—Kšœ˜—K˜šœŸœŸœŸœ˜3KšœŸœ"Ÿœ˜=K˜E—K˜š œŸœŸœŸœ˜0Kšœ ŸœŸœŸœ˜=KšœŸœ!Ÿœ˜@—K˜šœŸœŸœ˜4Kš œŸœ"ŸœŸœŸœ˜TKšŸœŸœŸœ˜K˜KšŸœ+ŸœŸœŸœ˜@KšŸœŸœŸœŸœ˜/K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&Kšœ Ÿœ"Ÿœ˜LK˜7KšœŸœ˜ šŸ˜KšœŸœB˜V—KšœŸœ˜#KšŸœŸœŸœŸœ˜8Kšœ˜—K˜KšœŸœ˜%KšœŸœ˜!KšŸœ˜Kšœ˜—K˜šœŸœŸœŸœ˜6KšœŸœ"Ÿœ˜=K˜H—K˜š œŸœŸœŸœŸœ˜YKšœŸœŸœ˜KšœŸœ$Ÿœ˜C—K˜š œŸœŸœ#Ÿœ"Ÿœ˜rKšŸœŸœ˜KšŸœŸœŸœ˜K˜KšŸœ+ŸœŸœŸœ˜@KšŸœŸœŸœŸœ˜/K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&Kšœ Ÿœ"Ÿœ˜LK˜7KšœŸœ˜ šŸ˜KšœŸœF˜[—KšœŸœ˜#KšŸœŸœŸœŸœ˜8Kšœ˜—K˜KšœŸœ˜%KšœŸœ˜!KšŸœ˜Kšœ˜—K˜š  œŸœŸœŸœ Ÿœ"Ÿœ˜lšŸœŸœŸœ˜K˜KšŸœ+ŸœŸœ˜9K˜šŸœŸœŸœŸœ˜ Kš œ ŸœŸœŸœŸœŸœ˜&Kšœ Ÿœ"Ÿœ˜LK˜7KšœŸœ˜ šŸ˜KšœŸœ Ÿœ6˜\—KšœŸœ˜#KšŸœŸœŸœŸœ˜8—KšŸœ˜K˜KšœŸœ˜%KšœŸœ˜!˜K˜———š œŸœŸœŸœŸœŸœŸœŸœŸœ(Ÿœ˜›KšŸœŸœ˜šŸœŸœŸœ˜K˜%K˜KšŸœ+ŸœŸœŸœ˜@Kš Ÿœ ŸœŸœŸœŸœ˜!K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&Kšœ Ÿœ"Ÿœ˜LK˜6KšœŸœ˜K˜FšŸœ˜KšŸœK˜OKšœ˜—K˜*KšŸœŸœŸœŸœ˜8Kšœ˜K˜—K˜&KšœŸœ˜ šŸœ˜K˜——Kšœ˜—K˜š œŸœŸœŸœŸœŸœŸœ Ÿœ˜wKšŸœŸœŸœ˜K˜K˜šœŸœŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜&Kšœ Ÿœ"Ÿœ˜LK˜7KšœŸœ˜ šŸ˜KšœŸœ?˜T—KšœŸœ˜#KšŸœŸœŸœŸœ˜8Kšœ˜—K˜KšœŸœ˜%KšœŸœ˜!K˜—K˜šœŸœŸœŸœ˜AKšœŸœŸœ˜KšœŸœ˜ š œŸœ˜K˜TK˜—K˜KšŸœ ŸœŸœŸœ˜šŸœŸœŸœ˜$˜KšŸœ*Ÿœ˜H—KšœŸœ˜+K˜—Kšœ/™/K˜@K•StartOfExpansion5[key: REF ANY, val: REF ANY, aList: List.AList]˜Kšœ`Ÿœ˜qKšŸœŸœŸœŸœ˜%šŸœŸœ™šœ™KšœM™M—KšŸœŸœ™K™—KšŸœŸœ˜ Kšœ˜—K˜š  œŸœŸœŸœŸœ˜HKšŸœ>ŸœŸœ˜LKšœN˜NKšœ˜—K˜Kšœ ŸœC˜RK˜K™ K™š œŸœ#Ÿœ"Ÿœ˜{šŸ ˜ Kšœ;Ÿœ˜EKšŸœ˜%KšŸœ˜—KšœŸœŸœŸœ˜KšœŸœ˜ Kšœ ŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœ˜KšœŸœCŸœ˜]K˜š œ˜šŸœ Ÿ˜˜Kšœ Ÿœ˜KšŸ˜—K˜—K˜Kš ŸœŸœŸœŸœŸœ˜K˜K˜GK˜Kšœ Ÿœ˜Kšœ˜—K˜Kšœ Ÿœ(˜6K˜KšœŸœ˜KšœFŸœ˜MKšœMŸœ˜SK˜šŸœŸ˜ KšœŸœŸœŸœ˜AKšœŸœ˜ K˜KšŸœŸœ/˜FK˜K˜9Kšœ6Ÿœ˜@K˜K˜AšŸœŸœŸ˜KšœZ˜Z—K˜KšŸœΟc ˜—Kšœ˜—K˜š  œŸœŸœŸœ2Ÿœ Ÿœ˜‚šŸ ˜ Kšœ;Ÿœ˜EKšŸœ˜%KšŸœ˜—Kš œŸœŸœ ŸœŸœ ˜'Kšœ ŸœŸœŸœ˜KšœŸœ˜ Kšœ ŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœAŸœ˜YKšœŸœA˜VKšœŸœA˜UKšœŸœAŸœ˜YKšœŸœŸœŸœ˜6K˜š œ˜šŸœ Ÿ˜˜Kšœ Ÿœ˜KšŸ˜—K˜—K˜šŸœ ŸœŸœ˜KšœŸœ˜ Kš ŸœŸœŸœŸœŸœ˜šœ˜K˜E—K˜K˜BK˜!KšœIŸœ˜RK˜Kšœ Ÿœ˜KšŸ˜K˜—K˜Kšœ4Ÿœ˜IK˜Kšœ Ÿœ˜Kšœ˜—š œ˜šŸœ Ÿœ˜K˜Kšœ Ÿœ˜KšŸ˜K˜—šŸœ ŸœŸœ˜K˜+Kš ŸœŸœŸœŸœŸœ˜šœ˜KšœF˜F—Kšœ Ÿœ˜Kšœ Ÿœ˜Kšœ Ÿœ˜˜K˜b—Kšœ Ÿœ-˜NKšœIŸœ˜RK˜Kšœ Ÿœ˜KšŸ˜K˜—K˜K˜SK˜Kšœ Ÿœ˜Kšœ˜—K˜šŸœ Ÿ˜KšœDŸœB˜‹—šŸœŸ˜ KšœŸœŸœŸœ˜AK˜šŸœ Ÿœ:˜JKšŸœ<˜@—KšŸœŸœŸœŸœ˜IK˜&K˜—KšŸœ  ˜Kšœ˜—K˜šœŸœ#Ÿœ"Ÿœ˜~šŸ ˜ Kšœ;Ÿœ˜EKšŸœ˜%KšŸœ˜—KšœŸœŸœŸœ˜KšœŸœ˜ Kšœ ŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœA˜VKšœŸœA˜UKšœŸœAŸœ˜YKšœŸœCŸœ˜]KšœŸœŸœŸœ˜6K˜š œ˜šŸœ Ÿœ˜K˜Kšœ Ÿœ˜KšŸ˜K˜—Kš ŸœŸœŸœŸœŸœ˜K˜šŸœ Ÿœ˜K˜+Kšœ Ÿœ˜Kšœ Ÿœ˜Kšœ Ÿœ˜˜K˜QKšœ Ÿœ-˜N—K˜šŸœ˜K˜OK˜K˜——Kšœ˜—K˜Kšœ Ÿœ(˜6KšœŸœ˜K˜šŸœŸ˜ KšœŸœŸœŸœ˜AKšœŸœ˜ K˜KšŸœŸœ Ÿœ)˜KK˜AKšœ6Ÿœ˜@K˜K˜AšŸœŸœŸ˜KšœZ˜Z—K˜—KšŸœ  ˜Kšœ˜—˜K˜—šœŸœŸœŸœŸœŸœ"Ÿœ˜‰šŸ ˜ Kšœ;Ÿœ˜EKšŸœ˜%KšŸœ˜KšœŸœ˜ Kšœ ŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœ˜KšœŸœCŸœ˜]KšœŸœ˜ š œ˜šŸœ Ÿ˜˜Kšœ Ÿœ˜KšŸ˜—K˜—KšŸœŸœŸœŸœ˜K˜K˜ K˜K˜;Kšœ Ÿœ˜Kšœ˜—K˜šŸœŸœŸ˜KšœŸœ ˜KšœŸœ˜KšœŸœ˜KšœŸœŸœ˜)KšœŸœ˜ K˜MK˜/šŸœŸœŸœŸ˜&KšœŸœ˜KšŸœŸœŸœŸœ˜2K˜KšŸœŸœŸœ˜#KšŸœ˜—K˜4Kšœ˜KšŸœ˜—K˜KšœŸœ˜KšœFŸœ˜MšœMŸœ˜SK˜—šŸœŸœŸœ!Ÿœ˜H˜Kšœ:˜:—šŸœŸœŸ˜KšœZ˜Z—K˜KšŸœ˜——Kšœ˜K˜—šœŸœŸœ˜7KšŸœŸœ$Ÿœ"˜WKšœ˜K˜—š œŸœŸœ˜0KšŸœŸœŸœ˜)K˜7K˜"Kšœ˜K˜—šœŸœŸœ˜8KšœŸœ˜KšŸ œ˜Kšœ˜K˜—šœŸœŸœ1Ÿœ˜MK˜4KšœŸœ˜KšœŸœ˜KšŸ œ˜Kšœ˜K˜—šœŸœŸœ˜/KšŸœŸœŸœ˜KšœŸœ ˜KšœŸœ+˜KKš Ÿœ ŸœŸœŸœ ˜6KšŸœŸœŸœ  ˜.KšœŸœ˜šŸœŸœ'Ÿœ˜OKšŸœ$˜(—Kšœ˜K˜—KšœM™MK˜šœŸœŸœŸœ˜SKšœŸœ˜K˜KšœŸœ˜K˜Kš œŸœŸœŸœŸœŸœ ŸœŸœŸœŸœ ˜UK™$K˜K˜%K˜šŸœŸœŸ˜$K˜KšŸœ ŸœŸœŸœ˜ K˜$Kšœ ˜.K˜ KšŸ˜—Kšœ1 ˜BKšŸœ ŸœŸœŸœ˜ KšŸœ˜ K˜K˜—š œŸœ.Ÿœ˜ZK™'K˜5K˜PK˜—K˜K˜—K˜š œŸœ.ŸœŸœŸœ"Ÿœ˜•Kš œŸœŸœŸœŸœŸœ ŸœŸœŸœŸœ ˜UKš œŸœŸœŸœŸœ˜^šœŸœ˜ KšŸœ ŸœŸœŸœ ˜N—KšœŸœ™(K˜FKšœ Ÿœ˜KšœŸœ˜K˜FšŸœ ŸœŸ˜Kšœ ˜ šœŸœ˜)Kšœ%˜%Kšœ.˜.K˜—˜Kšœ0Ÿœ˜C—Kšœ'˜'Kšœ˜K˜K˜K˜KšŸœ˜—Kšœ˜KšœŸœ  ™@KšŸœ ŸœŸœ˜šŸœŸ˜K˜E—šŸœŸœ˜šœP˜PKšœŸœŸœŸœ˜C—KšŸ˜K˜—K˜šœ˜K˜[—KšŸœŸœ.˜KK˜—K˜KšœŸœ˜'K˜Kšœ&Ÿœ˜*KšœŸœ˜K˜š œŸœ Ÿœ Ÿœ Ÿœ˜DKšœ˜Kšœ Ÿœ ˜KšœŸœ6Ÿœ˜SKšŸœŸœ Ÿœ ˜QK˜šŸœŸœ˜ ˜TKšœ˜—K˜KšŸœ˜ K˜K˜