DIRECTORY Atom USING [MakeAtom, PutProp], Basics USING [LowByte], Convert USING [RealFromRope, RopeFromReal], FS USING [Error, StreamOpen], IO, PascalBasic, PascalNoviceFiles, PrincOpsUtils USING [LongCopy], Real USING [DefaultSinglePrecision], RefText USING [TrustTextAsRope], Rope USING [Cat, Equal, Fetch, FromChar, Length], ViewerIO USING [CreateViewerStreams]; PascalNoviceFilesImpl: CEDAR PROGRAM IMPORTS Atom, Basics, Convert, FS, IO, PascalBasic, PrincOpsUtils, RefText, Rope, ViewerIO EXPORTS PascalNoviceFiles = BEGIN OPEN PascalBasic, PascalNoviceFiles; Control: PascalTextFile; Input: PUBLIC PascalTextFile; Output: PUBLIC PascalTextFile; Tty: PUBLIC PascalTextFile; openFiles: MesaFilePtr _ NIL; nilStream: IO.STREAM _ IO.CreateStream[ streamProcs: IO.CreateStreamProcs[ variety: inputOutput, class: $NilStream, getChar: NilGetChar, putChar: NilPutChar, endOf: NilEndOf, unsafeGetBlock: NilUnsafeGetBlock, unsafePutBlock: NilUnsafePutBlock, close: NilClose], streamData: NIL]; anonNo, ttyNo: PascalInteger _ 0; PrepareForTextRead: UNSAFE PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN IF file.baseFile = NIL OR file.baseFile.in = NIL THEN PascalAttachFile[file: @file.baseFile, dir: in, type: text]; END; PrepareForTextWrite: UNSAFE PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN IF file.baseFile = NIL OR file.baseFile.out = NIL THEN PascalAttachFile[file: @file.baseFile, dir: out, type: text]; END; PascalTextBREAK: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN NULL; -- !! Should do some sort of flush END; PascalTextGET: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN IF NOT file.validElement THEN PascalTextFinishGet[file]; file.validElement _ FALSE; END; PascalTextElement: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalChar] = TRUSTED BEGIN IF NOT file.validElement THEN PascalTextFinishGet[file]; RETURN[file.element]; END; PascalTextFinishGet: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN PrepareForTextRead[file]; file.element _ file.baseFile.in.GetChar[ ! IO.EndOfStream => GOTO EOF]; file.eoln _ FALSE; SELECT file.element FROM IN ['A..'Z] => IF NOT file.control.readUpperCase THEN file.element _ file.element - 'A + 'a; IN ['a..'z] => IF NOT file.control.readLowerCase THEN file.element _ file.element - 'a + 'A; '\N --CR-- => { file.eoln _ TRUE; file.lineNo _ file.lineNo + 1; file.element _ ' }; IN [0C..' ) => IF NOT file.control.readAllControlChars THEN file.element _ ' ; 'Z - 100B --Ctrl-Z-- => GOTO EOF; ENDCASE => NULL; file.validElement _ TRUE; EXITS EOF => { file.baseFile.eof _ file.eoln _ file.validElement _ TRUE; file.element _ ' }; END; PascalTextPUT: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN c: PascalChar; PrepareForTextWrite[file]; SELECT file.element FROM IN ['A..'Z] => IF NOT file.control.writeUpperCase THEN c _ file.element - 'A + 'a; IN ['a..'z] => IF NOT file.control.writeLowerCase THEN c _ file.element - 'a + 'A; '\N --CR-- => c _ file.element; IN [0C..' ) => IF NOT file.control.writeAllControlChars THEN file.element _ ' ; ENDCASE => c _ file.element; file.baseFile.out.PutChar[c]; END; PascalTextRESET: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN PrepareForTextRead[file]; file.baseFile.in.Reset[]; file.baseFile.eof _ FALSE; file.eoln _ TRUE; file.lineNo _ 1; file.element _ ' ; file.validElement _ FALSE; END; PascalTextREWRITE: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN PrepareForTextWrite[file]; file.baseFile.out.Reset[]; file.baseFile.out.SetLength[0 ! IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}]; file.baseFile.eof _ file.baseFile.in # nilStream; END; PascalTextPAGE: PUBLIC PROCEDURE [file: PascalTextFilePtr] = BEGIN PascalWriteLn[file: file]; PascalWriteChar[file: file, item: '\F --form feed--]; PascalWriteLn[file: file] END; PascalTextEOF: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [BOOLEAN] = TRUSTED BEGIN IF NOT file.validElement THEN PascalTextFinishGet[file]; RETURN[file.baseFile.eof] END; PascalTextEOLN: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [BOOLEAN] = TRUSTED BEGIN IF NOT file.validElement THEN PascalTextFinishGet[file]; RETURN[file.eoln] END; PascalBREAK: PUBLIC PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER] = {NULL}; -- !! Should be some form of Flush PascalGET: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] = UNCHECKED BEGIN PrepareForRead[file]; IF length = 1 THEN element^ _ file.in.GetChar[ ! IO.EndOfStream => {file.eof _ TRUE; CONTINUE}] ELSE IF length # file.in.UnsafeGetBlock[[base: element, startIndex: 0, count: length]] THEN file.eof _ TRUE; END; PascalPUT: PUBLIC PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] = TRUSTED BEGIN PrepareForWrite[file]; IF length = 1 THEN file.out.PutChar[LOOPHOLE[Basics.LowByte[LOOPHOLE[element^]]]] ELSE file.out.UnsafePutBlock[[base: element, startIndex: 0, count: length]]; END; PascalRESET: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length) OF UNSPECIFIED --] = UNCHECKED BEGIN PrepareForRead[file]; file.in.SetIndex[0]; file.eof _ FALSE; PascalGET[file, length, element]; END; PascalREWRITE: PUBLIC PROCEDURE [ file: PascalFilePtr, length: CARDINAL _ 0, element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED -- _ NIL] = TRUSTED BEGIN PrepareForWrite[file]; file.out.Reset[]; file.out.SetLength[0 ! IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}]; file.eof _ TRUE; END; PascalRead, PascalReadLong: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --, item: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] = UNCHECKED BEGIN IF length = 1 THEN item^ _ element^ ELSE PrincOpsUtils.LongCopy[from: element, nwords: length/2, to: item]; PascalGET[file: file, length: length, element: element]; END; PascalWrite, PascalWriteLong: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER TO -- ARRAY[0..length/2) OF -- UNSPECIFIED, item: LONG POINTER TO -- ARRAY[0..length/2) OF -- UNSPECIFIED] = UNCHECKED BEGIN IF length = 1 THEN element^ _ item^ ELSE PrincOpsUtils.LongCopy[from: item, nwords: length/2, to: element]; PascalPUT[file: file, length: length, element: element]; END; PascalEOF: PUBLIC PROCEDURE [file: PascalFilePtr] RETURNS [BOOLEAN] = TRUSTED { RETURN[IF file^ = NIL THEN TRUE ELSE file.eof]}; PascalReadLn: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN WHILE NOT PascalTextEOLN[file] DO PascalTextGET[file] ENDLOOP; PascalTextGET[file]; END; PascalWriteLn: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN PrepareForTextWrite[file]; file.baseFile.out.PutChar[('\N -- CR -- )]; IF file.baseFile.in = nilStream THEN file.element _ ' ; END; PascalReadInteger: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalInteger] = TRUSTED BEGIN PrepareForTextRead[file]; SkipBlanks[file]; SELECT file.element FROM '- => {PascalTextGET[file]; RETURN[-ReadDecimal[file].n]}; '+ => {PascalTextGET[file]; RETURN[ReadDecimal[file].n]}; ENDCASE => RETURN[ReadDecimal[file].n]; END; SkipBlanks: PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN WHILE NOT PascalTextEOF[file] AND (SELECT file.element FROM '-, '+, IN ['0..'9], '., IN ['a..'z], IN ['A..'Z] => FALSE, ENDCASE => TRUE) DO PascalTextGET[file] ENDLOOP; END; ReadDecimal: PROCEDURE [file: PascalTextFilePtr] RETURNS [n, digitCount: PascalInteger] = TRUSTED BEGIN n _ 0; digitCount _ 0; IF NOT PascalTextEOF[file] AND file.element NOT IN ['0..'9] THEN SIGNAL NumericInputError; WHILE file.element IN ['0..'9] DO n _ 10*n + (file.element - '0); digitCount _ digitCount + 1; PascalTextFinishGet[file]; ENDLOOP; END; PascalWriteInteger: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: PascalInteger, fieldMinLength: PascalInteger _ -1] = TRUSTED BEGIN sayMinus: BOOLEAN _ FALSE; digits: ARRAY [0..15] OF [0..9]; nDigits: [0..15] _ 0; i: PascalInteger; stream: IO.STREAM; PrepareForTextWrite[file]; stream _ file.baseFile.out; IF NOT fieldMinLength IN [0..1] THEN stream.PutChar[' ]; IF sayMinus _ item < 0 THEN { item _ -item; fieldMinLength _ fieldMinLength - 1}; IF item = 0 THEN {digits[0] _ 0; nDigits _ 1} ELSE WHILE item # 0 DO digits[nDigits] _ item MOD 10; nDigits _ nDigits + 1; item _ item/10; ENDLOOP; FOR i IN [1..fieldMinLength - nDigits] DO stream.PutChar[' ] ENDLOOP; IF sayMinus THEN stream.PutChar['-]; FOR i DECREASING IN [0..nDigits) DO stream.PutChar['0 + digits[i]] ENDLOOP; IF file.baseFile.in = nilStream THEN file.element _ '0 + digits[0]; END; PascalReadReal: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalReal] = TRUSTED BEGIN s: REF TEXT _ NEW[TEXT[50]]; s.length _ 0; PrepareForTextRead[file]; SkipBlanks[file]; WHILE (SELECT file.element FROM IN ['a..'z], IN ['A..'Z], '+, '-, '., IN ['0..'9] => TRUE, ENDCASE => FALSE) DO s[s.length] _ file.element; s.length _ s.length + 1; PascalTextFinishGet[file]; ENDLOOP; RETURN[Convert.RealFromRope[RefText.TrustTextAsRope[s]]]; END; PascalWriteReal: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: PascalReal, fieldMinLength, fracLength: PascalInteger _ -1] = TRUSTED BEGIN shortFracLength: INTEGER _ fracLength; PrepareForTextWrite[file]; IF NOT fieldMinLength IN [0..1] THEN file.baseFile.out.PutChar[' ]; PascalWriteString[file, Convert.RopeFromReal[ from: item, precision: IF fracLength < 0 THEN Real.DefaultSinglePrecision ELSE shortFracLength], fieldMinLength]; END; PascalReadChar: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalChar] = TRUSTED BEGIN c: PascalChar; PrepareForTextRead[file]; c _ PascalTextElement[file]; PascalTextGET[file]; RETURN[c]; END; PascalWriteChar: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: PascalChar, fieldMinLength: PascalInteger _ -1] = TRUSTED BEGIN i: PascalInteger; PrepareForTextWrite[file]; FOR i IN [1..fieldMinLength) DO file.baseFile.out.PutChar[' ] ENDLOOP; IF fieldMinLength#0 THEN BEGIN IF file.baseFile.in = nilStream THEN file.baseFile.out.PutChar[item]; file.element _ item; END; END; PascalReadBoolean: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalBoolean] = TRUSTED BEGIN b: PascalBoolean; PrepareForTextRead[file]; SkipBlanks[file]; SELECT file.element FROM 'T, 't => b _ TRUE; 'F, 'f => b _ FALSE; ENDCASE => {SIGNAL NumericInputError; b _ FALSE}; WHILE (SELECT file.element FROM IN ['a..'z], IN ['A..'Z] => TRUE, ENDCASE => FALSE) DO PascalTextFinishGet[file] ENDLOOP; RETURN[b]; END; PascalWriteBoolean: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: PascalBoolean, fieldMinLength: PascalInteger _ -1] = TRUSTED BEGIN IF NOT fieldMinLength IN [0..1] THEN PascalWriteChar[file, ' ]; PascalWriteString[file, IF item THEN "TRUE" ELSE "FALSE", fieldMinLength]; END; PascalReadArrayOfChar, PascalReadLongArrayOfChar: PUBLIC UNSAFE PROCEDURE [ file: PascalTextFilePtr, item: CharArrayPtr, arrayBound: PascalInteger] = UNCHECKED BEGIN v: CharArrayConcretePtr _ item; i: PascalInteger; PrepareForTextRead[file]; FOR i IN [1..arrayBound] DO v[i] _ PascalTextElement[file]; PascalTextGET[file]; ENDLOOP; END; PascalWriteArrayOfChar, PascalWriteLongArrayOfChar: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: CharArrayPtr, arrayBound: PascalInteger, fieldMinLength: PascalInteger _ -1] = TRUSTED BEGIN v: CharArrayConcretePtr _ LOOPHOLE[item]; i, arrayLim: PascalInteger; PrepareForTextWrite[file]; FOR i IN [arrayBound..fieldMinLength) DO file.baseFile.out.PutChar[' ] ENDLOOP; arrayLim _ IF fieldMinLength < 0 THEN arrayBound ELSE MIN[fieldMinLength, arrayBound]; FOR i IN [1..arrayLim] DO file.baseFile.out.PutChar[v[i]] ENDLOOP; IF file.baseFile.in = NIL AND ((fieldMinLength < 0 AND arrayLim > 0) OR fieldMinLength>0) THEN file.element _ IF arrayLim > 0 THEN v[arrayLim] ELSE ' ; END; ReadString: PRIVATE PROCEDURE [file: PascalTextFilePtr] RETURNS [r: ROPE]= TRUSTED BEGIN PrepareForTextRead[file]; IF file.baseFile.in = NIL THEN PascalTextRESET[file]; r _ ""; WHILE NOT PascalTextEOLN[file] AND NOT file.baseFile.eof DO r _ Rope.Cat[r, Rope.FromChar[file.element]]; PascalTextGET[file]; ENDLOOP; END; PascalWriteString, PascalWriteLongString: PUBLIC PROCEDURE [ file: PascalTextFilePtr, item: ROPE, fieldMinLength: PascalInteger _ -1] = TRUSTED BEGIN i, len, stringLim: PascalInteger; PrepareForTextWrite[file]; len _ item.Length[]; FOR i IN [len..fieldMinLength) DO file.baseFile.out.PutChar[' ] ENDLOOP; stringLim _ IF fieldMinLength < 0 THEN len ELSE MIN[fieldMinLength, len]; FOR i IN [0..stringLim) DO file.baseFile.out.PutChar[Rope.Fetch[item, i]] ENDLOOP; IF file.baseFile.in = NIL AND ((fieldMinLength < 0 AND stringLim > 0) OR fieldMinLength>0) THEN file.element _ IF stringLim > 0 THEN Rope.Fetch[item, stringLim-1] ELSE ' ; END; PascalCleanupFiles: PUBLIC PROCEDURE [] = BEGIN ENABLE IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}; FOR f: MesaFilePtr _ openFiles, f.openFileLink WHILE f#NIL DO IF f.in # NIL THEN f.in.Flush[]; IF f.out # NIL THEN f.out.Flush[]; IF f.inSource # NIL THEN f.inSource.Flush[]; IF f.inSource2 # NIL THEN f.inSource2.Flush[]; IF f.outDest # NIL THEN f.outDest.Flush[]; IF f.outDest2 # NIL THEN f.outDest2.Flush[]; ENDLOOP; END; CloseMesaFile: PROCEDURE [f: MesaFilePtr] = BEGIN IF f.in # NIL THEN {f.in.Close[]; f.in _ NIL}; IF f.out # NIL THEN {f.out.Close[]; f.out _ NIL}; IF f.inSource # NIL THEN {f.inSource.Close[]; f.inSource _ NIL}; IF f.inSource2 # NIL THEN {f.inSource2.Close[]; f.inSource2 _ NIL}; IF f.outDest # NIL THEN {f.outDest.Close[]; f.outDest _ NIL}; IF f.outDest2 # NIL THEN {f.outDest2.Close[]; f.outDest2 _ NIL}; END; PascalInventFileName: PUBLIC PROCEDURE [name: ROPE _ NIL] RETURNS [PascalFile] = BEGIN openFiles _ z.NEW[MesaFile _ [name: name, openFileLink: openFiles]]; RETURN[LOOPHOLE[openFiles]]; END; -- end of PascalInventFileName PascalAttachFile: PUBLIC PROCEDURE [ file: PascalFilePtr, dir: PascalFileDirection _ in, type: PascalFileType _ text] = TRUSTED BEGIN name: ROPE _ NIL; mFile: MesaFilePtr; RequestFileName: PROCEDURE[] = TRUSTED BEGIN PascalWriteLn[file: @Control]; PascalWriteString[file: @Control, item: "** File name = "]; name _ ReadString[file: @Control]; PascalReadLn[file: @Control]; END; BEGIN -- for EXITS IF file^ = NIL THEN {RequestFileName[]; file^ _ PascalInventFileName[name]} ELSE name _ file.name; mFile _ LOOPHOLE[file^]; Atom.PutProp[Atom.MakeAtom[name], $PascalFile, mFile]; CloseMesaFile[mFile]; SELECT TRUE FROM Rope.Equal[s1: name, s2: "Tty", case: FALSE] => BEGIN h: IO.STREAM _ IO.ROS[]; h.Put[[rope["PascalTty"]], [integer[ttyNo]]]; name _ h.RopeFromROS[]; h.Close[]; ttyNo _ ttyNo+1; GOTO UseWindow; END; Rope.Equal[s1: name, s2: "Nil", case: FALSE] => {mFile.in _ mFile.out _ nilStream}; ENDCASE => BEGIN IF Rope.Length[name]=0 THEN BEGIN h: IO.STREAM _ IO.ROS[]; h.Put[[rope["PascalAnonymous"]], [integer[anonNo]]]; name _ h.RopeFromROS[]; h.Close[]; anonNo _ anonNo+1; GOTO UseWindow; END; SELECT dir FROM in, both => BEGIN mFile.in _ FS.StreamOpen[name, $write ! FS.Error => IF error.group=user THEN GOTO UseWindow]; mFile.out _ nilStream; END; ENDCASE => -- out -- BEGIN mFile.out _ FS.StreamOpen[name, $create ! FS.Error => IF error.group=user THEN GOTO UseWindow]; mFile.in _ nilStream; END; END; EXITS UseWindow => BEGIN [in: mFile.in, out: mFile.out] _ ViewerIO.CreateViewerStreams[name: name]; END; END; END; -- of PascalAttachFile PrepareForRead: UNSAFE PROCEDURE [file: PascalFilePtr] = TRUSTED BEGIN IF file^ = NIL OR file^.in = NIL THEN PascalAttachFile[file: file, dir: in, type: binary]; END; PrepareForWrite: UNSAFE PROCEDURE [file: PascalFilePtr] = TRUSTED BEGIN IF file^ = NIL OR file^.out = NIL THEN PascalAttachFile[file: file, dir: out, type: binary]; END; NilGetChar: PROCEDURE [self: IO.STREAM] RETURNS [CHARACTER] = BEGIN ERROR IO.EndOfStream[self]; END; NilPutChar: PROCEDURE [self: IO.STREAM, char: CHARACTER] = {NULL}; NilEndOf: PROCEDURE [self: IO.STREAM] RETURNS [BOOLEAN] = {RETURN[TRUE]}; NilUnsafeGetBlock: PROCEDURE [self: IO.STREAM, block: IO.UnsafeBlock] RETURNS [INT] = {RETURN[0]}; NilUnsafePutBlock: PROCEDURE [self: IO.STREAM, block: IO.UnsafeBlock] = {NULL}; NilClose: PROCEDURE[self: IO.STREAM, abort: BOOLEAN _ FALSE] = {NULL}; Input _ PascalTextFile[baseFile: PascalInventFileName[name: "PascalInput"]]; Output _ PascalTextFile[baseFile: PascalInventFileName[name: "PascalOutput"]]; Tty _ PascalTextFile[baseFile: PascalInventFileName[name: "Tty"]]; Control _ PascalTextFile[baseFile: PascalInventFileName[name: "PascalControl"]]; TRUSTED {[in: Control.baseFile.in, out: Control.baseFile.out] _ ViewerIO.CreateViewerStreams[name: "PascalControl"]}; anonNo _ ttyNo _ 0; TRUSTED { PascalWriteString[file: @Control, item: "Pascal Cedar Runtime of May 9, 1985"]; PascalWriteLn[file: @Control]}; END. -- PascalNoviceFilesImpl ôfile: PascalNoviceFilesImpl.mesa last modified by McCreight, October 4, 1984 5:29:18 pm PDT last modified by Ramshaw, December 25, 1982 12:06 pm written by McCreight, December 19, 1980 10:44 AM Pascal files for the novice user: slow, but anything works Last Edited by: Starkweather, October 4, 1984 6:05:27 pm PDT V A R I A B L E S (all private) P R O C E D U R E S Text File Operations: Binary File Operations: formatted input and output: P R O C E D U R E S NOT Called by PasMesa (and hence, intended to be called as external procedures by the Pascal program, or else from Mesa code that implements such external procedures). text file operations As of this moment, file^ is a vaild non-NIL PascalFile. Unfortunately, we need a REF to a MesaFile rather than a LONG POINTER, so that reference counting will be turned on as we change the fields of this heap object. So, here we go. . . --following code commented out due to laziness of Cedar 5.0 converter: IF type = text THEN BEGIN mFile.inSource2 _ mFile.in; [in: mFile.inSource, out: mFile.outDest] _ ViewerIO.CreateViewerStreams[name]; mFile.in _ IO.CreateDribbleStream[stream: mFile.inSource2, dribbleTo: mFile.outDest]; END; --following code commented out due to laziness of Cedar 5.0 converter: IF type = text THEN BEGIN mFile.outDest2 _ mFile.out; [in: mFile.inSource, out: mFile.outDest] _ ViewerIO.CreateViewerStreams[name]; mFile.out _ IO.CreateDribbleStream[stream: mFile.outDest2, dribbleTo: mFile.outDest]; END; Stream operations Initialization Ê ˜Jšœ!™!Jšœ:™:Jšœ4™4Jšœ1™1J˜Jšœ;™;J™Jšœ˜ JšœÏc"˜)Jšœ˜J˜—šž œœ œ˜;Jšœ˜ Jšœœœ˜8Jšœœ˜Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ Jšœœœ˜8Jšœ˜Jšœ˜J˜—šžœœ œ˜AJšœ˜ J˜˜*Jšœœœ˜—Jšœ œ˜šœ˜šœ ˜šœœ˜&J˜&——šœ ˜šœœ˜&J˜&——šœŸœ˜Jšœ œ4˜D—šœ ˜Jšœœ"œ˜?—Jšœ Ÿ œœœ˜!Jšœœ˜—Jšœœ˜š˜šœ˜Jšœ4œ˜9J˜——Jšœ˜J˜—šž œœ œ˜;Jšœ˜ J˜J˜šœ˜šœ ˜Jšœœœ˜C—šœ ˜Jšœœœ˜C—JšœŸœ˜šœ ˜Jšœœ#œ˜@—Jšœ˜—J˜Jšœ˜J˜—šžœœ œ˜=Jšœ˜ J˜J˜Jšœœ˜Jšœ œ˜J˜J˜Jšœœ˜Jšœ˜J˜—šžœœ œ˜?Jšœ˜ J˜J˜šœ œ ˜+Jšœœ"œœ˜5—J˜1Jšœ˜J˜—šžœœ œ˜=Jš˜J˜Jšœ'Ÿ œ˜6J˜Jšœ˜J˜—š ž œœ œœœ˜MJšœ˜ Jšœœœ˜8Jšœ˜Jšœ˜J˜—š žœœ œœœ˜NJšœ˜ Jšœœœ˜8Jšœ ˜Jšœ˜J˜J˜——Jšœ™˜šž œœ œ˜Jšœœ˜&Jšœ œœœŸ"˜DJ˜—šž œœœ œ˜$Jšœœ˜&Jšœ œœŸ*œ˜CJš œ˜J˜šœ œ˜Jšœœœœ˜L—šœœ?˜FJšœœ œ˜%—Jšœ˜J˜—šž œœ œ˜Jšœœ˜&Jšœ œœŸ*œ˜CJšœ˜ J˜šœ ˜Jšœœœ ˜>—JšœH˜LJšœ˜J˜—šž œœœ œ˜&Jšœœ˜&Jšœ œœŸ(œ˜AJš œ˜J˜J˜Jšœ œ˜J˜!Jšœ˜J˜—šž œœ œ˜!Jšœœ˜*Jš œ œœŸ*œœ˜IJšœ˜ J˜J˜šœœ ˜"Jšœœ"œœ˜5—Jšœ œ˜Jšœ˜J˜—š ž œžœœœ œ˜5Jšœœ˜&Jšœ œœŸ*œ˜AJšœœœŸ*œ˜@Jš œ˜šœ œ˜#JšœC˜G—J˜8Jšœ˜J˜—š ž œžœœœ œ˜7Jšœœ˜&Jš œ œœœŸœ œ˜AJš œœœœŸœ œ˜@Jš œ˜šœ œ˜#JšœC˜G—J˜8Jšœ˜J˜—š ž œœ œœœœ˜OJš œœ œœœœ ˜0J˜——Jšœ™J˜˜šž œœ œ˜:Jšœ˜ Jšœœœœ˜>J˜Jšœ˜J˜—šž œœ œ˜;Jšœ˜ J˜JšœŸœ˜+Jšœœ˜7Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ J˜J˜šœ˜Jšœœ˜:Jšœœ˜9Jšœœ˜'—Jšœ˜J˜—šž œ œ˜1Jšœ˜ šœœ˜š˜šœœ˜Jš œœœ œ œ˜;Jšœœœœ˜0———Jšœ˜J˜—šž œ œ˜0Jšœ!˜(Jšœ˜ J˜J˜š œœœœœ ˜@Jšœ˜—šœœ ˜!J˜J˜J˜Jšœ˜—Jšœ˜J˜—šžœœ œ˜&J˜-J˜%Jšœ˜ Jšœ œœ˜Jšœœ œ˜ J˜J˜Jšœ œ˜J˜J˜Jšœœœœ˜8šœœ˜J˜3—Jšœ œ˜-š˜šœ ˜Jšœœ˜J˜J˜Jšœ˜——Jšœœœœ˜EJšœ œ˜$šœ œœ˜#Jšœœ˜'—Jšœœ˜CJšœ˜J˜—šžœœ œ˜:Jšœ˜Jšœ˜ Jš œœœœœ˜J˜ J˜J˜š˜šœœ˜Jšœ œœ œ˜:Jšœœ˜—J˜J˜J˜Jšœ˜—Jšœ3˜9Jšœ˜J˜—šžœœ œ˜#J˜*J˜1Jšœ˜ Jšœœ˜&J˜šœœœ˜$J˜—˜-J˜ J˜ Jšœœœ#˜Z—Jšœ˜J˜—šžœœ œ˜:Jšœ˜Jšœ˜ J˜J˜J˜J˜Jšœ˜ Jšœ˜J˜—šžœœ œ˜#J˜*J˜%Jšœ˜ J˜J˜šœœ˜Jšœœ˜&—šœ˜Jš˜Jšœœ!˜EJ˜Jšœ˜—Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ J˜J˜J˜šœ˜Jšœœ˜Jšœœ˜Jšœœœ˜1—š˜šœœ˜Jšœ œ œ˜!Jšœœœœ˜7——Jšœ˜ Jšœ˜J˜—šžœœ œ˜&J˜-J˜%Jšœ˜ šœœœ˜$J˜—Jšœœœœ˜JJšœ˜J˜—˜1Jšœœ œ˜J˜J˜0Jš œ˜J˜J˜J˜šœœ˜Jšœ5œ˜=—Jšœ˜J˜—˜3Jšœ œ˜J˜J˜J˜@Jšœ˜ Jšœœ˜)J˜J˜šœœ˜(Jšœœ˜&—˜ Jšœœ œœ˜K—šœœ˜Jšœ œ˜(—šœœ˜Jšœœœ˜@Jšœœœ œ˜8—Jšœ˜J˜—š ž œœ œœœ˜KJšœ˜ J˜Jšœœœ˜5J˜š œœœœ˜;J˜-J˜Jšœ˜—Jšœ˜J˜—šœžœœ œ˜Jšœœ˜J˜J˜Jšœ™J˜—J˜LJ˜NJ˜BJ˜Pšœ8˜?Jšœ5˜5J˜J˜—J˜Jšœ˜ ˜!J˜-—J˜J˜J˜JšœŸ˜J˜J˜J˜J˜J˜——…—Bv`t