DIRECTORY Ascii USING [CR, SP, TAB], Buttons USING [ButtonProc, Create], Commander USING [CommandProc, Handle, Register], CommandTool USING [DoCommand], Containers USING [ChildXBound], Convert USING [Error, IntFromRope, RopeFromInt], FileNames USING [CurrentWorkingDirectory], FS USING [ComponentPositions, Delete, EnumerateForNames, Error, ExpandName, NameProc], Icons USING [DrawIcon, IconFlavor, NewIconFromFile], Imager USING [DoSaveAll, MaskRectangleI, SetColor], ImagerBackdoor USING [invert], IO USING [CharClass, EndOf, EndOfStream, GetLineRope, GetTokenRope, IDProc, PutChar, PutRope, RIS, STREAM], Labels USING [Create, Set], Menus USING [CreateEntry, CreateMenu, GetNumberOfLines, InsertMenuEntry, Menu, MenuEntry, MenuProc], PieViewers USING [Create, Set], PressPrinter USING [Abort, CurrentProgress, CurrentState, CurrentStateMessage, Handle, IsAPressFile, ProgressProc, SendPressFile, State], PressScreen USING [NewPressName, PressScreen, Side], PrincOps USING [], PrincOpsUtils USING [], Process USING [CheckForAbort, Detach, Pause, priorityBackground, SecondsToTicks, SetPriority, Ticks], PseudoCursors USING [Create], Rope USING [Cat, Concat, Equal, Fetch, Find, IsEmpty, Length, ROPE, Substr], RuntimeError USING [UNCAUGHT], SafeStorage USING [ReclaimCollectibleObjects], TSFormat USING [FormatOneOutputFile], TSGlue USING [], TSOutput USING [Handle], TSViewer USING [RemoteOrLocalState, Tool, ToolRec], UserCredentials USING [Get], UserProfile USING [Boolean, Token], ViewerClasses USING [AdjustProc, PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerOps USING [AddProp, CreateViewer, DestroyViewer, EnumerateViewers, EnumProc, EstablishViewerPosition, FetchProp, FetchViewerClass, PaintViewer, RegisterViewerClass, SetMenu, SetOpenHeight], ViewerPrivate USING [selectedIcon], ViewerSpecs USING [captionHeight, iconHeight, iconWidth, menuHeight, scrollBarW, windowBorderSize], ViewerTools USING [GetContents, GetSelectedViewer, InhibitUserEdits, MakeNewTextViewer, SetContents, SetSelection]; TSViewerImpl: CEDAR MONITOR IMPORTS Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, Imager, ImagerBackdoor, Icons, IO, Labels, Menus, PieViewers, PressPrinter, PressScreen, Process, PseudoCursors, Rope, RuntimeError, SafeStorage, TSFormat, UserCredentials, UserProfile, ViewerOps, ViewerPrivate, ViewerSpecs, ViewerTools EXPORTS TSViewer = BEGIN OPEN TSViewer; ROPE: TYPE = Rope.ROPE; indent: INTEGER = 4; longIndent: INTEGER = 128; baseline: INTEGER = 16; rightIcon: Icons.IconFlavor _ Icons.NewIconFromFile["TSetter.icons", 0]; leftIcon: Icons.IconFlavor _ Icons.NewIconFromFile["TSetter.icons", 2]; NewButton: Menus.MenuProc = { IF mouseButton=yellow THEN ShowMessage[NARROW[clientData], doc[New]] ELSE { selectedViewer: ViewerClasses.Viewer _ ViewerTools.GetSelectedViewer[]; server: ROPE _ NIL; server _ IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars ! RuntimeError.UNCAUGHT => CONTINUE]]; IF server.Length < 2 THEN server _ NIL; [] _ NewTool[server]; }; }; doc: REF ARRAY MenuCode OF ROPE _ InitDoc[]; MenuCode: TYPE = {New, RightScreen, Screen, LeftScreen, All, Print, Get, StopSending, Stop, Pause}; InitDoc: PROCEDURE RETURNS [d: REF ARRAY MenuCode OF ROPE] = { d _ NEW[ARRAY MenuCode OF ROPE]; d[New] _ "New: Create a new typesetter tool for selected server."; d[RightScreen] _ ">: Print the right side of the screen."; d[Screen] _ "Screen: Print the whole screen."; d[LeftScreen] _ "<: Print the left side of the screen."; d[All] _ "All: Print all the documents in one press file."; d[Print] _ "Print: Print the documents named above."; d[Get] _ "Get: Add selected documents to the document queue."; d[StopSending] _ "StopSending: Abort transmission to the printer."; d[Stop] _ "Stop: Stop typesetting as soon as possible."; d[Pause] _ "Pause: Stop typesetting at end of current document."; }; NewTool: PUBLIC ENTRY PROCEDURE [server: ROPE, feedBack: IO.STREAM _ NIL] RETURNS [Tool] = { ENABLE UNWIND => NULL; data: Tool _ NEW[ToolRec _ [stop: FALSE, feedBack: feedBack]]; curY: INTEGER _ indent/2; NextY: PROCEDURE RETURNS [y:NAT] = {y _ curY _ curY+baseline}; container: ViewerClasses.Viewer _ ViewerOps.CreateViewer[ flavor: $TSetter, info: [name: IF server.Length = 0 THEN "TSetter" ELSE server, column: right, scrollable: FALSE ], paint: FALSE ]; menu: Menus.Menu _ Menus.CreateMenu[]; InsertMenuEntry: PROCEDURE [name: ROPE, proc: Menus.MenuProc, fork: BOOL _ FALSE, row: INTEGER _ 0, copy: BOOL _ FALSE, documentation: ROPE _ NIL, guarded: BOOL _ FALSE] = { menuEntry: Menus.MenuEntry ~ Menus.CreateEntry[name: name, proc: proc, clientData: data, documentation: documentation, fork: fork, guarded: guarded]; Menus.InsertMenuEntry[menu, menuEntry]; }; InsertMenuEntry[name: "New", proc: NewButton, fork: FALSE, documentation: doc[New]]; InsertMenuEntry[name: ">", proc: RightScreenButton, fork: TRUE, documentation: doc[RightScreen]]; InsertMenuEntry[name: "Screen", proc: ScreenButton, fork: TRUE, documentation: doc[Screen]]; InsertMenuEntry[name: "<", proc: LeftScreenButton, fork: TRUE, documentation: doc[LeftScreen]]; InsertMenuEntry[name: "All", proc: AllButton, fork: FALSE, documentation: doc[All]]; InsertMenuEntry[name: "Print", proc: PrintButton, fork: FALSE, documentation: doc[Print]]; InsertMenuEntry[name: "Get", proc: GetSelectionButton, fork: FALSE, documentation: doc[Get]]; InsertMenuEntry[name: "StopSending", proc: StopSendingButton, fork: FALSE, documentation: doc[StopSending]]; InsertMenuEntry[name: "Stop", proc: StopButton, fork: FALSE, documentation: doc[Stop] ]; InsertMenuEntry[name: "Pause", proc: PauseButton, fork: FALSE, documentation: doc[Pause]]; ViewerOps.SetMenu[container, menu]; data.nameButton _ Buttons.Create[ info:[name: "Documents: ", wx: indent, wy: curY, parent: container, border: FALSE], clientData: data, proc: NameButton, fork: FALSE, paint: FALSE, documentation: "Select the document name window. The right button empties it first." ]; PlaceChild[data.nameButton, 0, 0, TRUE]; data.nameBox _ ViewerTools.MakeNewTextViewer[ info:[wx: data.nameButton.wx + data.nameButton.ww, wy: curY+1, ww: 4*72, wh: data.nameButton.wh, parent: container, scrollable: TRUE, border: FALSE], paint: FALSE ]; PlaceChild[data.nameBox, 0, 0, FALSE]; Containers.ChildXBound[container, data.nameBox]; -- Let the text box grow to the right data.pie _ PieViewers.Create[parent: container, x: indent, y: NextY[]]; PlaceChild[data.pie, 1, 0, TRUE]; data.miniDisplay _ PseudoCursors.Create[parent: container, x: indent+20, y: curY]; PlaceChild[data.miniDisplay, 1, 0, TRUE]; data.messageBox _ ViewerTools.MakeNewTextViewer[ info: [wx: indent + 40, wy: curY, ww: 350, wh: 16, parent: container, scrollable: TRUE, border: TRUE], paint: FALSE ]; PlaceChild[data.messageBox, 1, 0, FALSE]; ViewerTools.InhibitUserEdits[data.messageBox]; data.serverName _ server; data.serverPie _ PieViewers.Create[parent: container, x: indent, y: NextY[], total: 1.0]; PlaceChild[data.serverPie, 2, 0, TRUE]; data.serverMsg _ ViewerTools.MakeNewTextViewer[ info: [wx: indent + 40, wy: curY, ww: 350, wh: 16, parent: container, scrollable: TRUE, border: TRUE], paint: FALSE ]; PlaceChild[data.serverMsg, 2, 0, FALSE]; ViewerTools.InhibitUserEdits[data.serverMsg]; data.copiesBox _ Buttons.Create[ info:[name: "Copies: ", wx: indent, wy: NextY[], parent: container, border: FALSE], clientData: data, proc: CopiesButton, fork: FALSE, paint: FALSE, documentation: "Set the number of copies. Gets reset to 1 after each file is sent." ]; PlaceChild[data.copiesBox, 3, 0, TRUE]; data.copiesBox _ ViewerTools.MakeNewTextViewer[ info:[wx: data.copiesBox.wx + data.copiesBox.ww, wy: curY+1, ww: 72, wh: data.nameButton.wh, parent: container, scrollable: FALSE, border: FALSE], paint: FALSE ]; PlaceChild[data.copiesBox, 3, 0, TRUE]; data.remoteBox _ Buttons.Create[ info:[name: "Remote or Local: ", wx: longIndent , wy: curY, parent: container, border: FALSE], clientData: data, proc: RemoteOrLocalButton, fork: FALSE, paint: FALSE ]; PlaceChild[data.remoteBox, 3, 0, TRUE]; data.remoteBox _ Labels.Create[ info:[name: "best performance", wx: data.remoteBox.wx+data.remoteBox.ww , wy: curY, parent: container, border: FALSE], paint: FALSE ]; data.remoteState _ bestPerformance; PlaceChild[data.remoteBox, 3, 0, TRUE]; data.tempPressLabel _ Buttons.Create[ info:[name: "Temporary Press Files: ", wx: indent , wy: NextY[], parent: container, border: FALSE], clientData: data, proc: TempPressButton, fork: FALSE, paint: FALSE ]; PlaceChild[data.tempPressLabel, 3, 1, TRUE]; data.tempPressLabel _ Labels.Create[ info:[name: "FALSE", wx: data.tempPressLabel.wx+data.tempPressLabel.ww , wy: curY, parent: container, border: FALSE], paint: FALSE ]; PlaceChild[data.tempPressLabel, 3, 1, TRUE]; TempPress[data, UserProfile.Boolean["Hardcopy.TemporaryPressFiles"]]; Containers.ChildXBound[container, data.copiesBox]; ViewerTools.SetContents[data.copiesBox, "1"]; ViewerOps.SetOpenHeight[container, curY+indent/2+baseline]; ViewerOps.PaintViewer[container, all]; ShowMessage[data, "Ready"]; RETURN [data] }; PositionInfoRec: TYPE = RECORD [ nVar: NAT, -- number of stretchy children above this one nFixed: NAT, -- number of fixed-height children above this one fixed: BOOLEAN -- true if this child is fixed in height ]; PlaceChild: PROCEDURE [viewer: ViewerClasses.Viewer, nVar, nFixed: NAT, fixed: BOOLEAN _ TRUE] = { ViewerOps.AddProp[viewer, $TSViewerPositionInfo, NEW[PositionInfoRec _ [nVar, nFixed, fixed]]]; }; SetViewerPosition: PROCEDURE [viewer: ViewerClasses.Viewer, x,y,w,h: INTEGER] = { OPEN viewer; vbs: INTEGER = IF border THEN ViewerSpecs.windowBorderSize ELSE 0; wx _ x; wy _ y; ww _ w; wh _ h; ch _ wh - (vbs+vbs) - (IF column=static OR parent#NIL THEN 0 ELSE ViewerSpecs.captionHeight); IF menu#NIL THEN ch _ ch - (Menus.GetNumberOfLines[menu]*ViewerSpecs.menuHeight); cx _ wx + vbs + (IF scrollable THEN ViewerSpecs.scrollBarW ELSE 0); cy _ wy + vbs; cw _ ww - (cx-wx) - vbs; }; TSViewerAdjust: ViewerClasses.AdjustProc = { varbaseline: NAT _ MAX[baseline, (self.ch-indent-2*baseline)/3]; FOR v: ViewerClasses.Viewer _ self.child, v.sibling UNTIL v=NIL DO WITH ViewerOps.FetchProp[v, $TSViewerPositionInfo] SELECT FROM positionInfo: REF PositionInfoRec => { ViewerOps.EstablishViewerPosition[viewer: v, x: v.wx, y: varbaseline*positionInfo.nVar + baseline*positionInfo.nFixed + indent/2, w: v.ww, h: IF positionInfo.fixed THEN baseline ELSE varbaseline ]; }; ENDCASE => NULL; ENDLOOP; }; TSViewerPaint: ViewerClasses.PaintProc = { drawIcon: PROC ~ { Icons.DrawIcon[flavor: IF self.column = left THEN leftIcon ELSE rightIcon, context: context, x: 0, y: 0, label: self.name]; }; IF self.iconic THEN { Imager.DoSaveAll[context, drawIcon]; IF ViewerPrivate.selectedIcon=self THEN { Imager.SetColor[context, ImagerBackdoor.invert]; Imager.MaskRectangleI[context, 0, 0, ViewerSpecs.iconWidth, ViewerSpecs.iconHeight]; } }; }; ShowMessage: PROCEDURE [tool: Tool, msg: ROPE] = { tool.messageLog _ msg _ tool.messageLog.Cat["\n", msg]; ViewerTools.SetContents[tool.messageBox, msg]; [] _ tool.messageBox.class.scroll[tool.messageBox, thumb, 100]; }; StopButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[Stop]] ELSE Stop[tool] }; Stop: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL; tool.stop _ TRUE; }; PauseButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[Pause]] ELSE Pause[tool] }; Pause: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL; tool.pause _ TRUE; }; StopSendingButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[StopSending]] ELSE StopSending[tool] }; StopSending: PUBLIC ENTRY PROCEDURE [tool: Tool] = {ENABLE UNWIND => NULL; tool.stopSending _ TRUE; }; NameButton: ENTRY Buttons.ButtonProc = {ENABLE UNWIND => NULL; tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton = blue THEN ViewerTools.SetContents[tool.nameBox, ""]; ViewerTools.SetSelection[tool.nameBox]; }; Copies: PUBLIC PROCEDURE [tool: Tool, copies: NAT] = { ViewerTools.SetContents[tool.copiesBox, Convert.RopeFromInt[copies]]; }; CopiesButton: Buttons.ButtonProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton = blue THEN ViewerTools.SetContents[tool.copiesBox, ""]; ViewerTools.SetSelection[tool.copiesBox]; }; TempPress: PUBLIC PROCEDURE [tool: Tool, temporaryPressFiles: BOOLEAN] = { tool.tempPress _ temporaryPressFiles; Labels.Set[tool.tempPressLabel, IF tool.tempPress THEN "TRUE" ELSE "FALSE"]; }; TempPressButton: Buttons.ButtonProc = { tool: Tool _ NARROW[clientData]; tool.tempPress _ NOT tool.tempPress; tool.selfDestruct _ FALSE; Labels.Set[tool.tempPressLabel, IF tool.tempPress THEN "TRUE" ELSE "FALSE"]; }; RemoteOrLocalButton: Buttons.ButtonProc = { tool: Tool _ NARROW[clientData]; currentOption: ROPE; tool.selfDestruct _ FALSE; currentOption _ ViewerTools.GetContents[tool.remoteBox]; tool.remoteState _ IF tool.remoteState = TSViewer.RemoteOrLocalState.LAST THEN TSViewer.RemoteOrLocalState.FIRST ELSE tool.remoteState.SUCC; Labels.Set[tool.remoteBox, SELECT tool.remoteState FROM bestPerformance => "best performance", localOnly => "local only", remoteOnly => "remote only" ENDCASE => "???"]; }; GetNames: ENTRY PROCEDURE [tool: Tool] RETURNS [gotIt: BOOLEAN _ TRUE, names: LIST OF ROPE _ NIL] = { ENABLE UNWIND => NULL; rope: ROPE ~ ViewerTools.GetContents[tool.nameBox]; length: NAT ~ rope.Length; i, start: NAT _ 0; c: CHAR; currentName: LIST OF ROPE; IF tool.pause OR tool.stop THEN {tool.process _ NIL; NOTIFY tool.idle; RETURN[FALSE, NIL]}; names _ CONS[NIL, NIL]; currentName _ names; DO WHILE i=length OR (c _ rope.Fetch[i]) = Ascii.SP OR c=Ascii.CR OR c=Ascii.TAB OR c=', OR c='; DO i _ i+1 ENDLOOP; IF i-start <= 0 THEN EXIT; currentName.rest _ CONS[rope.Substr[start: start, len: i-start], NIL]; currentName _ currentName.rest; WHILE i= length OR ~tool.singleOutputFile THEN EXIT; ENDLOOP; ViewerTools.SetContents[tool.nameBox, rope.Substr[start: i]]; names _ names.rest; IF names = NIL OR names.first.IsEmpty[] THEN { tool.process _ NIL; NOTIFY tool.idle; RETURN[FALSE, NIL]; }; }; FindFileViewer: PROC[file: Rope.ROPE] RETURNS[viewer: ViewerClasses.Viewer] = { FindViewer: ViewerOps.EnumProc = { IF Rope.Find[v.file, file, 0, FALSE] = 0 THEN {viewer _ v; RETURN[FALSE]} ELSE RETURN[TRUE]; }; ViewerOps.EnumerateViewers[FindViewer]; }; WaitUntilSaved: PROC [fileName: Rope.ROPE, tool: Tool] = { viewer: ViewerClasses.Viewer _ NIL; viewer _ FindFileViewer[fileName]; IF viewer # NIL AND viewer.newVersion THEN { SomeSaveInProgress: PROC RETURNS[ans: BOOL _ FALSE] = CHECKED { v: ViewerClasses.Viewer _ viewer; IF viewer.saveInProgress THEN RETURN[TRUE]; WHILE (v _ v.link) # NIL AND (v # viewer) DO IF v.saveInProgress THEN RETURN[TRUE]; ENDLOOP; }; IF NOT SomeSaveInProgress[] THEN { IF tool.feedBack = NIL THEN { ShowMessage[tool, Rope.Cat["***Please save ", viewer.name, ". . . \n"]]; } ELSE { tool.feedBack.PutRope[Rope.Cat["***Please save ", viewer.name, ". . . \n"]]; }; }; UNTIL SomeSaveInProgress[] DO Process.Pause[Process.SecondsToTicks[1]]; Process.CheckForAbort[]; ENDLOOP; IF SomeSaveInProgress[] THEN { IF tool.feedBack = NIL THEN { ShowMessage[tool, Rope.Cat["***Waiting for ", viewer.name, " to finish being saved. . . "]]; } ELSE { tool.feedBack.PutRope[Rope.Cat["***Waiting for ", viewer.name, " to finish being saved. . . "]]; }; }; WHILE SomeSaveInProgress[] DO TRUSTED { Process.Pause[Process.SecondsToTicks[1]]; Process.CheckForAbort[]; }; ENDLOOP; IF tool.feedBack = NIL THEN ShowMessage[tool, "ok\n"] ELSE tool.feedBack.PutRope["ok\n"]; }; }; InsureSaved: PROC [tool: Tool, names: LIST OF ROPE] = { wDir: ROPE = FileNames.CurrentWorkingDirectory[]; FOR loopNames: LIST OF ROPE _ names, loopNames.rest UNTIL loopNames = NIL DO currentName: ROPE = loopNames.first; WaitUntilSaved[ IF Rope.Find[currentName, ">"] < 0 AND Rope.Find[currentName, "/"] < 0 THEN FS.ExpandName[currentName, wDir].fullFName ELSE currentName, tool]; ENDLOOP; }; GetPressName: PROCEDURE [tool: Tool] RETURNS [pressName: ROPE] = { nameLen: INT _ 0; cp: FS.ComponentPositions; dirOmitted: BOOLEAN; [tool.currentName, cp, dirOmitted] _ FS.ExpandName[tool.currentName]; IF tool.currentName.Substr[cp.ext.start, cp.ext.length].Equal["Tioga", FALSE] THEN pressName _ tool.currentName.Substr[cp.base.start, cp.base.length] ELSE pressName _ tool.currentName.Substr[cp.base.start, cp.ext.start+cp.ext.length-cp.base.start]; IF tool.singleOutputFile THEN pressName _ pressName.Concat[".etc"]; pressName _ pressName.Concat[".press"]; IF cp.server.length = 0 THEN { pressName _ tool.currentName.Substr[0, cp.base.start].Concat[pressName]; }; IF tool.tempPress THEN pressName _ pressName.Concat["$"]; IF pressName.Equal[tool.pressName] THEN { WaitForSendIdle[tool]; ViewerTools.SetContents[tool.serverMsg, ""] } }; PrintButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[Print]] ELSE Print[tool] }; Print: PUBLIC ENTRY PROCEDURE [tool: Tool] = { ENABLE UNWIND => NULL; tool.pause _ tool.stop _ tool.stopSending _ FALSE; IF tool.process=NIL THEN TRUSTED {Process.Detach[tool.process _ FORK TypesetProcess[tool]]}; }; AllButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[All]] ELSE PrintAll[tool]}; PrintAll: PUBLIC PROCEDURE [tool: Tool] = { tool.singleOutputFile _ TRUE; Print[tool]; }; LeftScreenButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[LeftScreen]] ELSE Screen[tool, leftSide] }; ScreenButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[Screen]] ELSE Screen[tool, bothSides] }; RightScreenButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[RightScreen]] ELSE Screen[tool, rightSide] }; Screen: PUBLIC PROCEDURE [tool: Tool, side: PressScreen.Side] = { pressName: ROPE; TRUSTED {pressName _ PressScreen.NewPressName[]}; IF tool.tempPress THEN pressName _ pressName.Concat["$"]; TRUSTED {PressScreen.PressScreen[pressName, side]}; ShowMessage[tool, pressName.Concat[" completed"]]; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN { tool.pressName _ pressName; StartSending[tool]; }; }; TypesetProcess: PROCEDURE [tool: Tool] = { didNothing: BOOLEAN _ TRUE; gotIt: BOOLEAN; names: LIST OF ROPE; outputHandle: TSOutput.Handle _ NIL; TRUSTED {Process.SetPriority[Process.priorityBackground]}; WHILE ([gotIt: gotIt, names: names] _ GetNames[tool]).gotIt DO didNothing _ FALSE; IF tool.singleOutputFile THEN { tool.currentName _ names.first; ShowMessage[tool, tool.currentName]; tool.pressName _ GetPressName[tool]; IF PressPrinter.IsAPressFile[tool.currentName] THEN { tool.pressName _ tool.currentName; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool]; } ELSE { InsureSaved[tool, names]; TSFormat.FormatOneOutputFile[tool, names ! ABORTED => CONTINUE]; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool]; }; } ELSE { -- the "All" button means to format to one output file currentList: LIST OF ROPE _ CONS[NIL, NIL]; currentListTail: LIST OF ROPE _ currentList; tool.pressName _ NIL ; FOR n: LIST OF ROPE _ names, n.rest UNTIL n = NIL DO tool.currentName _ n.first; IF tool.pressName = NIL THEN tool.pressName _ GetPressName[tool]; ShowMessage[tool, tool.currentName]; IF PressPrinter.IsAPressFile[tool.currentName] THEN { IF currentList.rest # NIL THEN { currentList _ currentList.rest; TSFormat.FormatOneOutputFile[tool, currentList ! ABORTED => CONTINUE]; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool]; }; currentList _ CONS[NIL, NIL]; currentListTail _ currentList; ShowMessage[tool, tool.currentName]; tool.pressName _ tool.currentName; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool]; tool.pressName _ NIL; } ELSE { ShowMessage[tool, tool.currentName]; InsureSaved[tool, names]; currentListTail.rest _ CONS[n.first, NIL]; currentListTail _ currentListTail.rest; }; ENDLOOP; IF currentList.rest # NIL THEN { currentList _ currentList.rest; TSFormat.FormatOneOutputFile[tool, currentList ! ABORTED => CONTINUE]; IF NOT tool.debug AND NOT tool.stop AND tool.serverName.Length # 0 THEN StartSending[tool]; }; }; ENDLOOP; SafeStorage.ReclaimCollectibleObjects[]; tool.singleOutputFile _ FALSE; IF didNothing THEN ShowMessage[tool, "Ready"]; IF tool.selfDestruct THEN WaitForSendIdle[tool]; IF tool.stop OR tool.stopSending THEN tool.selfDestruct _ FALSE; IF tool.selfDestruct THEN ViewerOps.DestroyViewer[tool.messageBox.parent]; }; QueueRequest: PUBLIC ENTRY PROCEDURE [tool: Tool, documentName: ROPE] = { ENABLE UNWIND => NULL; queue: ROPE _ ViewerTools.GetContents[tool.nameBox]; IF queue.Length = 0 THEN queue _ documentName ELSE queue _ queue.Cat[" ", documentName]; ViewerTools.SetContents[tool.nameBox, queue]; }; GetSelectionButton: Menus.MenuProc = { tool: Tool _ NARROW[clientData, Tool]; tool.selfDestruct _ FALSE; IF mouseButton=yellow THEN ShowMessage[tool, doc[Get]] ELSE { selectedViewer: ViewerClasses.Viewer _ ViewerTools.GetSelectedViewer[]; sourceName: ROPE _ NIL; sourceName _ IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars ! RuntimeError.UNCAUGHT => CONTINUE]]; IF sourceName.Length <=1 THEN { IF (selectedViewer = NIL) THEN {ShowMessage[tool, "Selection not in text viewer"]; sourceName _ NIL} ELSE sourceName _ selectedViewer.name; }; QueueRequest[tool, sourceName]; }; }; WaitForIdle: PUBLIC ENTRY PROCEDURE [tool: Tool] = { ENABLE UNWIND => NULL; WHILE tool.process # NIL DO WAIT tool.idle ENDLOOP; WHILE tool.serverProcess # NIL DO WAIT tool.serverIdle ENDLOOP; }; WaitForSendIdle: PUBLIC ENTRY PROCEDURE [tool: Tool] = { ENABLE UNWIND => NULL; WHILE tool.serverProcess # NIL DO WAIT tool.serverIdle ENDLOOP; }; StartSending: PROCEDURE [tool: Tool] = { IF tool.serverName.Equal["*"] THEN DoShowPress[tool.pressName] ELSE MonitoredStartSending[tool]; }; MonitoredStartSending: ENTRY PROCEDURE [tool: Tool] = { ENABLE UNWIND => NULL; UNTIL tool.serverProcess = NIL DO WAIT tool.serverIdle ENDLOOP; TRUSTED {Process.Detach[tool.serverProcess _ FORK SendingProcess[tool, tool.pressName]]}; }; FinishSending: ENTRY PROCEDURE [tool: Tool] = { ENABLE UNWIND => NULL; tool.serverProcess _ NIL; BROADCAST tool.serverIdle; }; SendingProcess: PROCEDURE [tool: Tool, pressName: ROPE] = { ENABLE ABORTED => {FinishSending[tool]; GOTO Quit}; prevMsg: ROPE _ NIL; AbortablePause: PROC [seconds: CARDINAL] ~ { oneSecond: Process.Ticks ~ Process.SecondsToTicks[1]; THROUGH [0..seconds] DO IF tool.stopSending THEN GO TO Aborted; Process.Pause[oneSecond]; ENDLOOP; EXITS Aborted => DisplayMsg["Transmission aborted"]; }; DisplayMsg: PROC [rope: ROPE] ~ { IF prevMsg # rope THEN { ViewerTools.SetContents[tool.serverMsg, ViewerTools.GetContents[tool.serverMsg].Cat["\n",rope]]; [] _ tool.serverMsg.class.scroll[tool.serverMsg, thumb, 100]; }; prevMsg _ rope; }; tryAgain: BOOL _ FALSE; progressProc: PressPrinter.ProgressProc = { state: PressPrinter.State ~ handle.CurrentState; PieViewers.Set[tool.serverPie, 1.0-handle.CurrentProgress]; IF tryAgain=FALSE OR state#aborted THEN DisplayMsg[handle.CurrentStateMessage]; IF state=serverBusy OR state=serverTimeout THEN {tryAgain _ TRUE; handle.Abort}; IF tool.stopSending THEN {tryAgain _ FALSE; handle.Abort}; }; copies: INT _ 1; copies _ MAX[0, Convert.IntFromRope[ViewerTools.GetContents[tool.copiesBox] ! Convert.Error => CONTINUE]]; IF copies > 0 THEN { printedBy: ROPE _ UserProfile.Token["Hardcopy.PrintedBy", ""]; DO tryAgain _ FALSE; [] _ PressPrinter.SendPressFile[ fileName: pressName, server: tool.serverName, progressProc: progressProc, copies: copies, userName: IF printedBy.Length = 0 THEN UserCredentials.Get[].name ELSE printedBy ]; IF NOT tryAgain THEN EXIT; AbortablePause[30]; ENDLOOP; }; IF TemporaryName[pressName] THEN { FS.Delete[pressName ! FS.Error => { DisplayMsg[error.explanation]; CONTINUE }]; }; FinishSending[tool]; EXITS Quit => {} }; TemporaryName: PROC [rope: ROPE] RETURNS [BOOL] ~ { fullFName: ROPE; cp: FS.ComponentPositions; [fullFName, cp] _ FS.ExpandName[rope]; RETURN [fullFName.Fetch[cp.ext.start+cp.ext.length-1] = '$] }; GetName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ { name _ NIL; name _ IO.GetTokenRope[stream, IO.IDProc ! IO.EndOfStream => CONTINUE].token; }; FileNameBreakProc: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = ' OR char = ' OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetFileName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ { name _ NIL; name _ IO.GetTokenRope[stream, FileNameBreakProc ! IO.EndOfStream => CONTINUE].token; }; GetLine: PROC [stream: IO.STREAM] RETURNS [line: ROPE] ~ { line _ NIL; line _ IO.GetLineRope[stream ! IO.EndOfStream => CONTINUE]; }; DoShowPress: PROC [pressFileName: ROPE] ~ { [] _ CommandTool.DoCommand[Rope.Concat["ShowPress ", pressFileName], NIL]; }; TSetterExecCommand: Commander.CommandProc = { tool: Tool; stream: IO.STREAM _ IO.RIS[cmd.commandLine]; serverName: ROPE _ GetName[stream]; files: ROPE _ NIL; WHILE NOT IO.EndOf[stream] DO token: ROPE _ GetFileName[stream]; IF token # NIL THEN { ENABLE FS.Error => {IF error.group=user THEN {cmd.out.PutRope[error.explanation]; cmd.out.PutChar['\n]; CONTINUE} ELSE REJECT}; CatProc: FS.NameProc = { files _ files.Cat[" ", fullFName]; RETURN[TRUE]; }; IF token.Find["*"] = -1 THEN [] _ CatProc[FS.ExpandName[token].fullFName] ELSE { IF token.Find["!"] = -1 THEN token _ token.Concat["!H"]; FS.EnumerateForNames[pattern: token, proc: CatProc]; }; }; ENDLOOP; IF serverName.Length=0 THEN serverName _ UserProfile.Token["Hardcopy.PressPrinter", ""]; tool _ NewTool[serverName]; IF files.Length > 0 THEN {tool.selfDestruct _ TRUE; QueueRequest[tool, files]}; Print[tool]; }; tSViewerClass: ViewerClasses.ViewerClass = NEW[ViewerClasses.ViewerClassRec _ ViewerOps.FetchViewerClass[$Container]^]; tSViewerClass.paint _ TSViewerPaint; tSViewerClass.adjust _ TSViewerAdjust; tSViewerClass.icon _ private; tSViewerClass.bltH _ none; tSViewerClass.bltV _ none; ViewerOps.RegisterViewerClass[$TSetter, tSViewerClass]; Commander.Register[ key: "TSetter", proc: TSetterExecCommand, doc: "Create a typesetter viewer for specified server, and use it to print listed documents" ]; END. TSViewerImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, April 25, 1985 1:22:42 pm PST Rick Beach, June 3, 1985 2:11:22 pm PDT Bob Hagmann November 22, 1985 11:53:46 am PST ViewerTools.SetContents[tool.copiesBox, "1"]; -- should set it to one here only if there is nothing more to print, but I didn't figure out how to determine that yet... The line cache in Tioga 1 is global and used by both scrolling and selection. Invalidate it as a good citizen (guess scrolling was never expected to be asynchronous) TEditSelection.InvalidateLineCache[]; CHANGE LOG Michael Plass, September 15, 1982 9:53 am. ENABLE UNWIND => NULL. Michael Plass, September 15, 1982 10:51 am. Changed Rope.SP, etc, to refer to Ascii. Michael Plass, September 15, 1982 10:51 am. Removed "Clover" default. Michael Plass, September 15, 1982 11:54 am. Fixed it so unknown font message is not obliterated. Michael Plass, September 15, 1982 12:07 pm. Revised calculation of press file names. Michael Plass, September 15, 1982 12:13 pm. Replaced ! ANY with ! SafeStorage.NarrowFault. Michael Plass, September 16, 1982 1:01 pm. Revised creation of press files. Michael Plass, November 1, 1982 11:30 am. Converted to Tioga fomatting, made cursorProc and progressProc SAFE Michael Plass, November 12, 1982 3:22 pm. Made some of the windows scrollable and growable. Michael Plass, November 15, 1982 3:08 pm. Added StopSending and Screen buttons. Michael Plass, November 17, 1982 9:28 am. Fixed screen buttons to reset the stopSending bit. Michael Plass, November 17, 1982 11:35 am. Added calls to SafeStorage. Michael Plass, November 18, 1982 10:45 am. Added yellow-button documentation. Michael Plass, December 10, 1982 4:19 pm. Added clientData to New menu item. Michael Plass, December 10, 1982 4:18 pm. Added ExecCommand. Michael Plass, December 10, 1982 5:33 pm. Added selfDestuct changes to: ToolRec, StopButton, PauseButton, StopSendingButton, NameButton, CopiesButton, TempPress, TempPressButton, GetFirstName, PrintButton, AllButton, LeftScreenButton, ScreenButton, RightScreenButton, TypesetProcess, GetSelectionButton, ExecCommand Michael Plass, December 10, 1982 6:17 pm. Bug fix in TypesetProcess John Maxwell, January 20, 1983 1:54 pm. changes to: TSViewerImpl, Print, Screen, TypesetProcess, FormatOneFile, StartSending, ExecCommand Michael Plass, March 10, 1983 8:30 am. changes to: rightIcon, leftIcon, InitDoc, NewTool Michael Plass, May 2, 1983 9:05 am. Removed uses of UserExec, fixed bug in GetFirstName. Michael Plass, May 27, 1983 11:15 am. Changed so foo.tioga produces foo.press., IMPORTS Edited on May 27, 1983 11:11 am, by Beach changes to: TSViewerPaint to force a clear viewer when adjusting the viewer sizes. Edited on June 1, 1983 9:40 am, by Beach changes to: tSViewerClass, TSViewerPaint, TSViewerPaint Edited on June 20, 1983 3:56 pm, by Beach changes to: SendingProcess to use Hardcopy.PrintedBy if its defined in the user profile. Edited on August 10, 1983 5:24 pm, by Beach changes to: DIRECTORY, IMPORTS, TSViewerPaint Edited on August 12, 1983 2:39 pm, by Beach changes to: ToolRec, NewTool, TSetterExecCommand, PressScreenTool, PressScreenToolRec, NewPressScreenTool, NextY (local of NewPressScreenTool), FlashImageButton, SelectedImageButton, WholeScreenButton, RightColumnButton, LeftColumnButton, MagnificationFactorButton, SetCornersButton, BlackBorder, PageMarginButton, PressScreenExecCommand, Commander, Commander, mode, BoxAdjustNotify, Clip (local of BoxAdjustNotify), BlackBorder Edited on August 15, 1983 2:52 pm, by Beach changes to: DIRECTORY, IMPORTS, InsertMenuEntry, FlashImageButton, SelectedImageButton, WholeScreenButton, RightColumnButton, LeftColumnButton, ReadScreenCorners, ConvertRopeToReal, vaTIP, NewPressScreenTool, TSetterExecCommand, Commander, }, Screen, MenuCode, NewTool, NewTool, ToolRec, InsertMenuEntry (local of NewTool), ToolRec, GetPressName Edited on August 18, 1983 12:46 pm, by Beach changes to: TSViewerPaint Edited on August 19, 1983 12:56 pm, by Beach changes to: NewTool, InsertMenuEntry (local of NewTool) Edited on October 26, 1983 9:08 am, by Beach changes to: DIRECTORY, IMPORTS, progressProc (local of SendingProcess) Michael Plass, December 7, 1983 12:36 pm: Cedar 5 conversion (FS, Convert, UserCredentials, IO.GetTokenRope, IO.GetLineRope) Michael Plass, December 12, 1983 2:11 pm: Carried local directory name from input file to output file. Michael Plass, February 21, 1984 9:46:50 am PST: Fixed file-name-on-header bug. Rick Beach, May 3, 1985 2:04:22 pm PDT changes to: SendingProcess increased pause before retrying to send to a busy or timed-out server from 2 seconds to 60 seconds, moved the code to reset the copies box from FinishSending to the end of the TypesetProcess loop. Rick Beach, May 3, 1985 8:30:33 pm PDT changes to: progressProc (local of SendingProcess), SendingProcess, AbortablePause (local of SendingProcess), DisplayMsg (local of SendingProcess), DIRECTORY, =, FinishSending Bob Hagmann May 20, 1985 1:31:57 pm PDT changes to: NewTool, cursorProc, =, DIRECTORY, IMPORTS, WaitUntilSaved, InsureSaved, WaitUntilSaved, GetNames, GetFirstName, Screen Bob Hagmann November 21, 1985 4:40:47 pm PST added RemoteOrLocalButton to handle Summoner options changes to: NewTool, RemoteOrLocalButton Bob Hagmann November 22, 1985 11:53:46 am PST changes to: NewTool Ê ¦– "Cedar" style˜codešÏc™Kšœ Ïmœ1™˜QKšœ Ÿœ´˜ÃKšœŸœ˜#Kšœ ŸœR˜cKšœ Ÿœb˜s—K˜KšÐln œŸ ˜KšŸœ@Ÿœ!ŸœË˜¹KšŸœ ˜šœŸœŸœ ˜KšŸœŸœŸœ˜K˜KšœŸœ˜Kšœ Ÿœ˜Kšœ Ÿœ˜K˜HK˜GK˜šÏn œ˜KšŸœŸœ Ÿœ˜DšŸœ˜K˜GKšœŸœŸœ˜š œŸœŸœŸœŸœŸœŸ˜KšŸœŸœ5˜@Kšœ ŸœŸœ˜$——KšŸœŸœ Ÿœ˜'K˜K˜—K˜K˜—KšœŸ œ ŸœŸœ ˜,šœ ŸœU˜cK˜—š ¡œŸ œŸœŸ œ ŸœŸœ˜>Kš œŸœŸœ ŸœŸœ˜ K˜BK˜:K˜.K˜8K˜;K˜5K˜>K˜CK˜8K˜AK˜K˜—š¡œŸ œŸ œ Ÿœ ŸœŸœŸœŸœ ˜]KšŸœŸœŸœ˜Kšœ ŸœŸœŸœ ˜>KšœŸœ ˜Kš¡œŸ œŸœŸœ˜>˜!˜K˜šœ ŸœŸœ Ÿœ˜=KšœŸ˜ K˜—KšœŸ˜ K˜——K˜&š¡œŸ œŸœŸœŸœŸœ ŸœŸœŸœŸœ ŸœŸœ˜­K˜•Kšœ'˜'K˜—Kšœ4Ÿœ˜TKšœ:Ÿœ#˜aKšœ:Ÿœ˜\Kšœ9Ÿœ"˜_Kšœ4Ÿœ˜TKšœ8Ÿœ˜ZKšœ=Ÿœ˜]KšœDŸœ#˜lKšœ6Ÿœ˜XKšœ8Ÿœ˜ZK˜#˜!KšœLŸœ˜SK˜K˜KšœŸœ˜ KšœŸœ˜ K˜TK˜—Kšœ"Ÿœ˜(˜-˜`KšœŸœ Ÿœ˜4—KšœŸ˜ K˜—KšœŸœ˜&Kšœ1%˜VK˜GKšœŸœ˜!K˜RKšœ#Ÿœ˜)˜0KšœRŸœ Ÿœ˜fKšœŸ˜ K˜—Kšœ"Ÿœ˜)K˜.K˜K˜YKšœ!Ÿœ˜'˜/KšœRŸœ Ÿœ˜fKšœŸ˜ K˜—Kšœ!Ÿœ˜(K˜-šœ ˜ KšœLŸœ˜SK˜K˜KšœŸœ˜ KšœŸœ˜ K˜SKšœ˜—Kšœ!Ÿœ˜'˜/˜\KšœŸœ Ÿœ˜5—KšœŸ˜ K˜—Kšœ!Ÿœ˜'šœ ˜ KšœWŸœ˜^K˜Kšœ˜KšœŸœ˜ KšœŸ˜ K˜—Kšœ!Ÿœ˜'˜KšœoŸœ˜vKšœŸ˜ K˜—Kšœ#˜#Kšœ!Ÿœ˜'šœ%˜%Kšœ\Ÿœ˜cK˜K˜KšœŸœ˜ KšœŸ˜ K˜—Kšœ&Ÿœ˜,˜$KšœnŸœ˜uKšœŸ˜ K˜—Kšœ&Ÿœ˜,KšœE˜EK˜2K˜-K˜;K˜&K˜KšŸœ˜ Kšœ˜K˜—šœŸœŸœ˜ KšœŸœ-˜8KšœŸœ1˜>KšœŸœ(˜8K˜K˜—š ¡ œŸ œ.Ÿœ ŸœŸœ˜bKšœ1Ÿœ+˜_K˜K˜—š¡œŸ œ)Ÿœ˜QKšŸœ˜ Kš œŸœŸœŸœŸœ˜BK˜Kš œŸœŸœŸœŸœŸœ˜]KšŸœŸœŸœA˜QKšœŸœ ŸœŸœ˜CK˜K˜Kšœ˜K˜—š¡œ˜,Kšœ ŸœŸœ*˜@šŸœ1ŸœŸœŸ˜BšŸœ/ŸœŸ˜>šœŸœ˜&šœ5˜5KšœK˜KK˜KšœŸœŸœ Ÿœ ˜7K˜—Kšœ˜—KšŸœŸœ˜—KšŸœ˜—K˜K˜—š¡ œ˜*šœ Ÿœ˜•StartOfExpansionr[flavor: Icons.IconFlavor, context: Graphics.Context, x: INTEGER _ 0, y: INTEGER _ 0, label: ROPE _ NIL]šœŸœŸœ Ÿœ ˜JKšœ˜Kšœ˜—Kšœ˜—šŸœ Ÿœ˜Kšœ$˜$šŸœ Ÿœ˜)Kšœ0˜0KšœT˜TKšœ˜—Kšœ˜—K˜K˜—š¡ œŸ œŸœ˜2Kšœ7˜7Kšœ.˜.Kšœ?˜?K˜K˜—š¡ œ˜Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ˜7KšŸœ ˜Kšœ˜K˜—š¡œŸœŸœŸ œŸœŸœŸœ˜CKšœ Ÿœ˜K˜K˜—š¡ œ˜Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ˜8KšŸœ ˜Kšœ˜K˜—š¡œŸœŸœŸ œŸœŸœŸœ˜DKšœ Ÿœ˜K˜K˜—š¡œ˜%Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ$˜>KšŸœ˜Kšœ˜K˜—š¡ œŸœŸœŸ œŸœŸœŸœ˜JKšœŸœ˜K˜K˜—š ¡ œŸœŸœŸœŸœ˜>Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ+˜EK˜'K˜K˜—š¡œŸœŸ œŸœ˜6K˜EK˜K˜—š¡ œ˜$Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ-˜GK˜)K˜K˜—š¡ œŸœŸ œ#Ÿœ˜JK˜%Kšœ ŸœŸœŸœ ˜LK˜K˜—š¡œ˜'Kšœ Ÿœ ˜ KšœŸœ˜$KšœŸœ˜Kšœ ŸœŸœŸœ ˜LK˜K˜—š¡œ˜+Kšœ Ÿœ ˜ KšœŸœ˜KšœŸœ˜Kšœ8˜8Kš œŸœ0ŸœŸœŸœŸœŸœ˜ŒšœŸœŸ˜7Kšœ&˜&Kšœ˜Kšœ˜KšŸœ ˜—K˜K˜—š¡œŸœŸ œŸœ ŸœŸœ ŸœŸœŸ œ˜eJšŸœŸœŸœ˜JšœŸœ)˜3JšœŸœ˜Jšœ Ÿœ˜JšœŸœ˜Jšœ ŸœŸœŸœ˜šŸœ Ÿœ Ÿ˜Jš œŸœŸœ ŸœŸ œ˜;—JšœŸœŸœŸœ˜Jšœ˜šŸ˜šŸœ ŸœŸœŸœ ŸœŸœ ŸœŸœŸœ˜`JšŸœ Ÿœ˜—Jšœ ˜ šŸœ ŸœŸœŸœ ŸœŸœ ŸœŸœŸœ˜^JšŸœ Ÿœ˜—JšŸœŸœŸœ˜JšœŸœ*Ÿœ˜FJšœ˜šŸœ ŸœŸœŸœ ŸœŸœ ŸœŸœŸœ˜`JšŸœ Ÿœ˜—JšŸœ ŸœŸœŸœ˜3JšŸœ˜—J˜=Jšœ˜šŸœ ŸœŸœŸœ˜.JšœŸœ˜JšŸœ ˜JšŸœŸœŸœ˜J˜—J˜J˜—code1š¡œŸœ Ÿœ˜%LšŸœ"˜)˜"šŸœŸœ˜)LšŸœŸœŸœ˜ LšŸœŸœŸœ˜—L˜—L˜'L˜L˜—š¡œŸœŸœ˜:LšœŸœ˜#Lšœ"˜"šŸœ ŸœŸœŸœ˜,š ¡œŸœŸœŸœŸœŸœ˜@Lšœ!˜!LšŸœŸœŸœŸœ˜+šŸœŸœŸœŸ˜,LšŸœŸœŸœŸœ˜&LšŸœ˜—L˜—šŸœŸœŸœ˜"šŸœŸœŸœ˜LšœH˜HL˜—šœŸœ˜LšœL˜LL˜—L˜—šŸœ˜šŸ˜Lšœ)˜)Lšœ˜—LšŸœ˜—šŸœŸœ˜šŸœŸœŸœ˜Lšœ\˜\L˜—šœŸœ˜Lšœ`˜`L˜—L˜—šŸœŸ˜šŸœ˜ Lšœ)˜)Lšœ˜L˜—LšŸœ˜—LšŸœŸœŸœŸœ˜YL˜—L˜L˜—š ¡ œŸœŸœŸœŸœ˜7JšœŸœ'˜1š Ÿœ ŸœŸœŸœŸœ ŸœŸ˜LJšœ Ÿœ˜$šœ˜šŸœ!Ÿœ!˜GJšŸœŸœ(˜/JšŸœ ˜—Jšœ˜—JšŸœ˜—J˜J˜—š¡ œŸ œŸœ Ÿœ˜BKšœ Ÿœ˜KšœŸœ!Ÿœ˜/Kšœ%ŸÏbœ˜EšŸœEŸœŸ˜RKšœB˜B—KšŸœ^˜bKšŸœŸœ&˜CKšœ'˜'šŸœŸœ˜KšœH˜HK˜—KšŸœŸœ#˜9šŸœ!Ÿœ˜)K˜K˜+K˜—Kšœ˜K˜—š¡ œ˜Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ˜8KšŸœ ˜Kšœ˜K˜—š¡œŸœŸœŸ œ˜.KšŸœŸœŸœ˜Kšœ,Ÿœ˜2Kš ŸœŸœŸœŸœ Ÿœ˜\Kšœ˜K˜—š¡ œ˜Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ˜6KšŸœ˜K˜—š¡œŸœŸ œ˜+KšœŸœ˜K˜ K˜K˜—š¡œ˜$Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ#˜=KšŸœ˜Kšœ˜—š¡ œ˜ Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ˜9KšŸœ˜Kšœ˜—š¡œ˜%Kšœ Ÿœ ˜ KšœŸœ˜KšŸœŸœ$˜>KšŸœ˜Kšœ˜K˜—š¡œŸœŸ œ)˜AKšœ Ÿ˜KšŸœ*˜1KšŸœŸœ#˜9KšŸœ,˜3Kšœ2˜2š ŸœŸœ ŸœŸœ ŸœŸœ˜IKšœ˜K˜K˜—K˜K˜—š¡œŸ œ˜*Jšœ ŸœŸœ˜JšœŸœ˜JšœŸœŸœŸœ˜Jšœ Ÿœ˜$JšŸœ3˜:šŸœ7Ÿ˜>Jšœ Ÿœ˜šŸœŸœ˜Jšœ˜J˜$Jšœ$˜$šŸœ-Ÿœ˜5J˜"š ŸœŸœ ŸœŸœ ŸœŸ˜GJ˜—J˜—šŸœ˜J˜Jšœ+ŸœŸœ˜@Jš ŸœŸœ ŸœŸœ ŸœŸœ˜[J˜—J˜—šœŸœ6˜>Jš œ ŸœŸœŸœŸœŸœŸœ˜+JšœŸœŸœŸœ˜,JšœŸœ˜š ŸœŸœŸœŸœŸœŸœŸ˜4Jšœ˜JšŸœŸœŸœ%˜AJ˜$šŸœ-Ÿœ˜5šŸœŸœŸœ˜ Jšœ˜Jšœ1ŸœŸœ˜FJš ŸœŸœ ŸœŸœ ŸœŸœ˜[J˜—JšœŸœŸœŸœ˜Jšœ˜J˜$J˜"š ŸœŸœ ŸœŸœ ŸœŸ˜GJ˜—JšœŸœ˜J˜—šŸœ˜J˜$J˜JšœŸœ Ÿœ˜*Jšœ'˜'J˜—JšŸœ˜—šŸœŸœŸœ˜ Jšœ˜Jšœ2ŸœŸœ˜GJš ŸœŸœ ŸœŸœ ŸœŸœ˜[J˜—J˜—JšŸœ˜—J˜(JšœŸœ˜JšŸœ Ÿœ˜.JšŸœŸœ˜0JšŸœ ŸœŸœŸœ˜@JšŸœŸœ1˜JJšœ˜J˜—š ¡ œŸœŸœŸ œŸœ˜IKšŸœŸœŸœ˜KšœŸœ)˜4KšŸœŸœ˜-KšŸœ&˜*Kšœ-˜-K˜K˜—š¡œ˜&Kšœ Ÿœ˜&KšœŸœ˜KšŸœŸœ˜6šŸœ˜K˜GKšœ ŸœŸœ˜š œ ŸœŸœŸœŸœŸœŸ˜OšŸœŸœ5˜@Kšœ ŸœŸœ˜$——šŸœŸœ˜šŸœŸœŸ˜KšœAŸœ˜E—KšŸœ"˜&K˜—K˜K˜—Kšœ˜K˜—š¡ œŸœŸœŸ œ˜4KšŸœŸœŸœ˜Kš ŸœŸœŸœŸœ Ÿœ˜3Kš ŸœŸœŸœŸœŸœ˜?K˜K˜—š¡œŸœŸœŸ œ˜8KšŸœŸœŸœ˜Kš ŸœŸœŸœŸœŸœ˜?K˜K˜—š¡ œŸ œ˜(KšŸœŸœ˜>KšŸœ˜!K˜K˜—š¡œŸœŸ œ˜7KšŸœŸœŸœ˜Kš ŸœŸœŸœŸœŸœ˜?KšŸœ&Ÿœ(˜YK˜K˜—š¡ œŸœŸ œ˜/KšŸœŸœŸœ˜KšœŸœ˜KšŸ œ˜K™¨K˜K˜—š¡œŸ œŸœ˜;KšŸœŸœŸœ˜3Kšœ ŸœŸœ˜š¡œŸœ Ÿœ˜,J˜5šŸœŸ˜JšŸœŸœŸœŸœ ˜'J˜JšŸœ˜—šŸ˜Jšœ.˜.—J˜—š¡ œŸœŸœ˜!šŸœŸœ˜Kšœ`˜`Kšœ=˜=K™MK™WKšœ%™%Kšœ˜—Kšœ˜K˜—Kšœ ŸœŸœ˜š¡ œ˜+Kšœ0˜0K˜;KšŸœ ŸœŸœŸœ(˜OKšŸœŸœŸœ Ÿœ˜PKšŸœŸœ Ÿœ˜:K˜—KšœŸœ˜Kšœ ŸœSŸœ˜jšŸœ Ÿœ˜Kšœ Ÿœ/˜>šŸ˜Kšœ Ÿœ˜˜ K˜K˜K˜K˜Kšœ ŸœŸœŸœ ˜PK˜—KšŸœŸ ˜K˜KšŸœ˜—K˜—šŸœŸœ˜"šŸœ!˜#Kšœ˜KšŸ˜Kšœ˜—K˜—K˜KšŸœ ˜K˜K˜—š ¡ œŸœŸœŸœŸœ˜3Kšœ Ÿœ˜KšœŸœ˜KšœŸœ˜&KšŸœ5˜;K˜K˜—š ¡œŸœ ŸœŸœŸœŸœ˜:KšœŸœ˜ Kš œŸœŸœ ŸœŸœ˜MK˜K˜—– "cedar" styleš ¡œŸœŸœŸœŸœ˜?KšŸœ Ÿœ Ÿœ Ÿœ Ÿœ ŸœŸœ˜UKšŸœ ˜Kšœ˜K˜—š ¡ œŸœ ŸœŸœŸœŸœ˜>KšœŸœ˜ KšœŸœ*ŸœŸœ˜UK˜K˜—š ¡œŸœ ŸœŸœŸœŸœ˜:KšœŸœ˜ KšœŸœŸœŸœ˜;K˜K˜—š¡ œŸœŸœ˜+KšœEŸœ˜JK˜K˜—š¡œ˜-Kšœ ˜ Kš œŸœŸœŸœŸœ˜,Kšœ Ÿœ˜#KšœŸœŸœ˜šŸœŸœŸœŸ˜KšœŸœ˜"šŸœ ŸœŸœ˜KšŸœŸœ ŸœŸœ<ŸœŸœŸœ˜šœ Ÿœ ˜Kšœ"˜"KšŸœŸœ˜ K˜—KšŸœŸœŸœ˜IšŸœ˜KšŸœŸœ˜8KšŸœ2˜4Kšœ˜—Kšœ˜—KšŸ˜—KšŸœŸœ=˜XKšœ˜KšŸœŸœŸœ˜OKšœ ˜ K˜K˜—˜*KšŸœI˜L—K˜K˜$K˜&K˜Kšœ˜Kšœ˜K˜7K˜šœ˜Kšœ˜Kšœ˜Kšœ\˜\K˜——K˜KšŸœ˜K˜šŸœŸ™ Kšœ+ŸœŸœŸœ™AKšœ9Ÿœ™TK™EK™`K™TKšœ7Ÿœ ™ZK™KK™mK™[K™OK™\K™FK™MKšœL™LKšœ<™<šœ;™;Kšœÿ™ÿ—KšœC™Cšœ'™'Kšœa™a—KšœX™XKšœX™XKšœNÏr ™W™)Kšœ £ œ9™R—™(Kšœ £+™7—™)Kšœ £œ>™X—™+Kšœ £!™-—™+Kšœ £dœ£öœ£ ™¬—™+Kšœ ££œ£™Ù—™,Kšœ £ ™—™,Kšœ £œ™7—™,Kšœ £ œ™F—Kšœ\ŸœŸœ ™|Kšœf™fKšœO™O—™&Kš œ £œc£œ,£ œ£œ™ß—™&Kšœ £ œ£ œ£ œ£™¯—™'Kšœ £w™ƒ—™,Kšœ4™4Kšœ £™(—™-Kšœ £™—K™—…—jV