DIRECTORY Basics USING [RawBytes], FS USING [Close, defaultStreamOptions, nullOpenFile, Open, OpenFile, StreamFromOpenFile, StreamOptions], IO USING [STREAM, Close, GetIndex, GetLength, UnsafeBlock, SetIndex, UnsafeGetBlock], PressFormat, PressReader, RealConvert USING [BcplToIeee], Rope USING [ROPE, FromProc]; PressReaderImpl: CEDAR PROGRAM IMPORTS FS, IO, PF: PressFormat, RealConvert, Rope EXPORTS PressReader = BEGIN OPEN PressReader; ROPE: TYPE = Rope.ROPE; bytesPerPressRecord: CARDINAL = 512; indexDistanceThreshold: INT _ 500; Handle: PUBLIC TYPE = REF PressReaderRec; PressReaderRec: PUBLIC TYPE = RECORD [ file: FS.OpenFile _ FS.nullOpenFile, stream1: IO.STREAM _ NIL, stream2: IO.STREAM _ NIL, nRecs: INT _ 0, nParts: INT _ 0, pdStart: INT _ 0, pdRecs: INT _ 0, currentPart: INT _ 0, pType: PartType, pStart: INT _ 0, pRecs: INT _ 0, padding: INT _ 0, atObject: BOOL _ FALSE, atDots: BOOL _ FALSE, dataPlace: INT, -- bytes! dataLength: INT, -- words! entityStack: REF EntityStack _ NIL]; PressReaderError: PUBLIC ERROR [errorCode: ErrorCode] = CODE; bcplMaxLength: CARDINAL = 255; -- maximum length of a BCPL string BcplString: TYPE = LONG POINTER TO BcplStringBody; BcplStringBody: TYPE = MACHINE DEPENDENT RECORD [ body: PACKED ARRAY[0..0) OF CHARACTER ]; BcplReal: TYPE = MACHINE DEPENDENT RECORD [ sign: [0..1], exp: [0..377B], sigbit: [0..1], topmantissa: [0..77B], restofmantissa: [0..177777B] ]; EntityStack: TYPE = RECORD[start, length, data: INT _ 0, next: REF EntityStack _ NIL]; FromOpenFile: PUBLIC PROC [openFile: FS.OpenFile] RETURNS [handle: Handle] = TRUSTED { docDirV: PF.DDV; lengthInBytes: INT; handle _ NEW[PressReaderRec]; { options: FS.StreamOptions _ FS.defaultStreamOptions; options[closeFSOpenFileOnClose] _ FALSE; options[tiogaRead] _ FALSE; handle.file _ openFile; handle.stream1 _ FS.StreamFromOpenFile[openFile: handle.file, streamOptions: options]; handle.stream2 _ FS.StreamFromOpenFile[openFile: handle.file, streamOptions: options]; lengthInBytes _ handle.stream1.GetLength[]; }; IF lengthInBytes = 0 OR (lengthInBytes MOD bytesPerPressRecord # 0) THEN ERROR PressReaderError[FileNotAPressFile]; --bad length ReadBlock[handle, lengthInBytes-bytesPerPressRecord, [LP[@docDirV], 0, SIZE[PF.DDV]*2]]; IF docDirV.Passwd # PF.PressPasswd THEN ERROR PressReaderError[FileNotAPressFile]; -- bad password handle.nRecs _ lengthInBytes/bytesPerPressRecord; IF docDirV.nRecs # handle.nRecs THEN ERROR PressReaderError[FileNotAPressFile]; --bad record count handle.nParts _ docDirV.nParts; handle.pdStart _ docDirV.pdStart; handle.pdRecs _ docDirV.pdRecs; }; -- FromOpenFile OpenPressFile: PUBLIC PROC [name: ROPE] RETURNS [handle: Handle] = { handle _ FromOpenFile[FS.Open[name, $read]]; }; -- OpenPressFile GetDocumentDirectory: PUBLIC PROC [handle: Handle] RETURNS [DocumentDirectory] = TRUSTED { docDirV: PF.DDV; IF handle = NIL THEN ERROR PressReaderError[BadHandle]; ReadBlock[handle, (handle.nRecs-1)*bytesPerPressRecord, [LP[@docDirV], 0, SIZE[PF.DDV]*2]]; RETURN[NEW[DocumentDirectoryRec _ [ passwd: docDirV.Passwd, nRecs: docDirV.nRecs, nParts: docDirV.nParts, pdStart: docDirV.pdStart, pdRecs: docDirV.pdRecs, backP: docDirV.Backp, date: PF.DoubleToLC[docDirV.date], fCopy: docDirV.fCopy, lCopy: docDirV.lCopy, fPage: docDirV.fPage, lPage: docDirV.lPage, fileName: BcplStringToRope[ArrayCardinalToBcplString[@docDirV.FileStr]], creator: BcplStringToRope[ArrayCardinalToBcplString[@docDirV.CreatStr]], dateText: BcplStringToRope[ArrayCardinalToBcplString[@docDirV.DateStr]]]]]; }; -- GetDocumentDirectory GetParts: PUBLIC PROC [handle: Handle, partNumber: INT, pageProc: PageProc _ NIL, fontDirectoryProc: FontDirectoryProc _ NIL] = TRUSTED { partEntry: PF.PE; currentPart: INT; upToPart: INT; IF handle = NIL THEN ERROR PressReaderError[BadHandle]; IF partNumber = 0 THEN { currentPart _ 1; upToPart _ handle.nParts; } ELSE IF partNumber NOT IN [1..handle.nParts] THEN ERROR PressReaderError[PartNotFound] ELSE currentPart _ upToPart _ partNumber; WHILE currentPart <= upToPart DO ReadBlock[ handle, handle.pdStart*bytesPerPressRecord+(currentPart-1)*SIZE[PF.PE]*2, [LP[@partEntry], 0, SIZE[PF.PE]*2]]; handle.pType _ SELECT LOOPHOLE[partEntry.Type, INTEGER] FROM PF.PETypePage => printedPage, PF.PETypeFont => fontDirectory, < 0 => private, > 1 => other, ENDCASE => ERROR PressReaderError[BadPartType]; handle.pStart _ partEntry.pStart; handle.pRecs _ partEntry.pRecs; handle.padding _ partEntry.Padding; SELECT handle.pType FROM printedPage => IF pageProc # NIL THEN pageProc[handle, [printedPage, partEntry.Type, handle.pStart, handle.pRecs, handle.padding]]; fontDirectory => IF fontDirectoryProc # NIL THEN fontDirectoryProc[handle, [fontDirectory, partEntry.Type, handle.pStart, handle.pRecs, handle.padding]]; ENDCASE => ERROR PressReaderError[BadPartType]; currentPart _ currentPart+1; ENDLOOP; }; -- GetParts GetFonts: PUBLIC PROC [handle: Handle, fontEntryProc: FontEntryProc _ NIL] = TRUSTED { fontEntry: PF.FE; partEntry: PF.PE; pStart, currentPart: INT; fontStart: INT _ 0; IF handle = NIL THEN ERROR PressReaderError[BadHandle]; IF fontEntryProc = NIL THEN RETURN; IF handle.pType # fontDirectory THEN { -- search all parts for FontDirectory FOR currentPart IN [0..handle.nParts) DO ReadBlock[handle, handle.pdStart*bytesPerPressRecord+currentPart*SIZE[PF.PE]*2, [LP[@partEntry], 0, SIZE[PF.PE]*2]]; IF partEntry.Type = PF.PETypeFont THEN {pStart _ partEntry.pStart; EXIT;} REPEAT FINISHED => ERROR PressReaderError[NoFontDirectoryPart]; ENDLOOP; } ELSE pStart _ handle.pStart; DO ReadBlock[handle, pStart*bytesPerPressRecord+fontStart, [LP[@fontEntry], 0, SIZE[PF.FE]*2]]; IF fontEntry.length = 0 THEN EXIT; IF fontEntry.fam[0] = 0 AND fontEntry.fam[1] = 0 AND fontEntry.destn = 255 THEN { handle.dataLength _ fontEntry.length-4; -- SIZE[length, set, fno, m, all-ones, zero] handle.dataPlace _ pStart*bytesPerPressRecord+fontStart+8; handle.atObject _ TRUE; fontEntryProc[[ length: fontEntry.length, fontSet: fontEntry.set, font: fontEntry.fno, firstChar: fontEntry.destm, lastChar: fontEntry.destn, family: NIL, face: [0, 0.0, none, none, none], source: 0, size: 0, rotation: 0 ]]; handle.atObject _ FALSE; } ELSE { fontEntryProc[[ length: fontEntry.length, fontSet: fontEntry.set, font: fontEntry.fno, firstChar: fontEntry.destm, lastChar: fontEntry.destn, family: BcplStringToRope[ArrayByteToBcplString[@fontEntry.fam]], face: DecodeFace[fontEntry.face], source: fontEntry.source, size: LOOPHOLE[fontEntry.siz, INTEGER], rotation: fontEntry.rotn ]]; }; fontStart _ fontStart+fontEntry.length*2; ENDLOOP; }; -- GetFonts GetPage: PUBLIC PROC [handle:Handle, entityProc: EntityProc _ NIL] = TRUSTED { temp: REF EntityStack; length: CARDINAL; entityTrailer: PF.EH; IF handle = NIL THEN ERROR PressReaderError[BadHandle]; IF handle.pType # printedPage THEN ERROR PressReaderError[CurrentPartNotAPage]; handle.entityStack _ NEW[EntityStack]; handle.entityStack.start _ (handle.pStart+handle.pRecs)*bytesPerPressRecord-handle.padding*2; DO ReadBlock[handle, handle.entityStack.start-SIZE[CARDINAL]*2, [LP[@length], 0, SIZE[CARDINAL]*2]]; IF length = 0 THEN EXIT; temp _ NEW[EntityStack _ [start: handle.entityStack.start-length*2, next: handle.entityStack]]; handle.entityStack _ temp; ENDLOOP; handle.entityStack _ handle.entityStack.next; -- pop the empty entry on top WHILE handle.entityStack # NIL DO ReadBlock[handle, handle.entityStack.start-SIZE[PF.EH]*2, [LP[@entityTrailer], 0, SIZE[PF.EH]*2]]; handle.entityStack.length _ entityTrailer.Length; handle.entityStack.data _ PF.DoubleToLC[entityTrailer.Dstart]; entityProc[handle, [ entityType: entityTrailer.Type, fontSet: entityTrailer.Fontset, dataStart: PF.DoubleToLC[entityTrailer.Dstart], dataLength: PF.DoubleToLC[entityTrailer.Dlength], Xe: entityTrailer.Xe, Ye: entityTrailer.Ye, xLeft: entityTrailer.Xleft, yBottom: entityTrailer.Ybottom, width: entityTrailer.Width, height: entityTrailer.Height, length: entityTrailer.Length]]; handle.entityStack _ handle.entityStack.next; ENDLOOP; }; -- GetPage GetCommands: PUBLIC PROC [handle: Handle, showCharactersProc: ShowCharactersProc, skipProc: SkipProc, spacingProc: SpacingProc, spaceProc: SpaceProc, positionProc: PositionProc, colorProc: ColorProc, fontProc: FontProc, noOpProc: NoOpProc, showRectangleProc: ShowRectangleProc, showObjectProc: ShowObjectProc, showDotsProc: ShowDotsProc, copyProc: CopyProc, alternativeProc: AlternativeProc, badProc: BadProc] = TRUSTED { length: CARDINAL; stringBuffer: PACKED ARRAY [0..256) OF CHARACTER; integerBuffer: INTEGER _ 0; value: INTEGER _ 0; rectangleBuffer: MACHINE DEPENDENT RECORD [width, height: INTEGER]; alternativeBuffer: MACHINE DEPENDENT RECORD [ELtypes: CARDINAL, ELbytes, DLbytes: PF.Double]; opBuffer: MACHINE DEPENDENT RECORD [opcode: PF.BYTE, byteArg: PF.BYTE]; dataPlace, commandPlace, commandEnd: INT; dataLength: INT; dotsLength: PF.Double; IF handle = NIL THEN ERROR PressReaderError[BadHandle]; IF handle.entityStack = NIL THEN ERROR PressReaderError[NoEntity]; dataPlace _ handle.pStart*bytesPerPressRecord+handle.entityStack.data; commandPlace _ handle.entityStack.start-handle.entityStack.length*2; commandEnd _ commandPlace+(handle.entityStack.length-SIZE[PF.EH])*2; WHILE commandPlace < commandEnd DO ReadBlock[handle, commandPlace, [LP[@opBuffer], 0, 2]]; -- read Opcode and one byte BEGIN OPEN opBuffer; SELECT opcode FROM IN [PF.EShowShort .. PF.ESkipShort) => { length _ opcode-PF.EShowShort+1; IF showCharactersProc # NIL THEN { stringBuffer[0] _ LOOPHOLE[opcode-PF.EShowShort+1, CHARACTER]; ReadBlock[handle, dataPlace, [LP[@stringBuffer], 1, length+1]]; showCharactersProc[showCharactersShort, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]]; }; dataPlace _ dataPlace+length; commandPlace _ commandPlace+1; }; IN [PF.ESkipShort..PF.EShowSkip) => { length _ opcode-PF.ESkipShort+1; IF skipProc # NIL THEN skipProc[skipCharactersShort, length]; dataPlace _ dataPlace+length; commandPlace _ commandPlace+1; }; IN [PF.EShowSkip..PF.ESpaceXShort) => { length _ opcode-PF.EShowShort+1; IF showCharactersProc # NIL THEN { stringBuffer[0] _ LOOPHOLE[opcode-PF.EShowShort+1, CHARACTER]; ReadBlock[handle, dataPlace, [LP[@stringBuffer], 1, length+1]]; showCharactersProc[showCharactersAndSkip, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]]; }; dataPlace _ dataPlace+length+1; -- skip byte commandPlace _ commandPlace+1; }; IN [PF.ESpaceXShort..PF.ESpaceYShort) => { IF spacingProc # NIL THEN spacingProc[setSpaceXShort, (opcode-PF.ESpaceXShort)*256+byteArg]; commandPlace _ commandPlace+2; }; IN [PF.ESpaceYShort..PF.EFont) => { IF spacingProc # NIL THEN spacingProc[setSpaceYShort, (opcode-PF.ESpaceXShort)*256+byteArg]; commandPlace _ commandPlace+2; }; IN [PF.EFont..PF.EShortMax] => { IF fontProc # NIL THEN { value _ opcode-PF.EFont; fontProc[value]; }; commandPlace _ commandPlace+1; }; PF.ENop, IN (PF.EShortMax..PF.ESkipControlImmediate) => { --available and spare IF noOpProc # NIL THEN noOpProc[]; commandPlace _ commandPlace+1; }; PF.ESkipControlImmediate => { IF skipProc # NIL THEN skipProc[skipControlBytesImmediate, byteArg]; commandPlace _ commandPlace+2+byteArg; }; PF.EAlternative => { IF alternativeProc # NIL THEN { ReadBlock[handle, commandPlace+1, [LP[@alternativeBuffer], 0, 10]]; alternativeProc[alternativeBuffer.ELtypes, PF.DoubleToLC[alternativeBuffer.ELbytes], PF.DoubleToLC[alternativeBuffer.DLbytes]]; }; commandPlace _ commandPlace+11; }; PF.EOnlyOnCopy => { IF copyProc # NIL THEN copyProc[byteArg]; commandPlace _ commandPlace+2; }; PF.ESetX, PF.ESetY => { IF positionProc # NIL THEN { ReadBlock[handle, commandPlace+1, [LP[@integerBuffer], 0, 2]]; positionProc[ SELECT opcode FROM PF.ESetX => setX, PF.ESetY => setY, ENDCASE => ERROR PressReaderError[UnexpectedOpCode], integerBuffer]; }; commandPlace _ commandPlace+3; }; PF.EShow => { length _ byteArg; IF showCharactersProc # NIL THEN { stringBuffer[0] _ LOOPHOLE[byteArg, CHARACTER]; ReadBlock[handle, dataPlace, [LP[@stringBuffer], 1, length+1]]; showCharactersProc[showCharacters, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]]; }; dataPlace _ dataPlace+length; commandPlace _ commandPlace+2; }; PF.ESkip => { IF skipProc # NIL THEN skipProc[skipCharacters, byteArg]; dataPlace _ dataPlace+byteArg; commandPlace _ commandPlace+2; }; PF.ESkipControl => { -- should get the type byte too ReadBlock[handle, commandPlace+1, [LP[@integerBuffer], 0, 2]]; IF skipProc # NIL THEN skipProc[skipControlBytes, integerBuffer]; dataPlace _ dataPlace+integerBuffer; commandPlace _ commandPlace+4; }; PF.EShowImmediate => { IF showCharactersProc # NIL THEN { stringBuffer[0] _ LOOPHOLE[1, CHARACTER]; stringBuffer[1] _ LOOPHOLE[byteArg, CHARACTER]; showCharactersProc[showCharacterImmediate, 1, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]]; }; commandPlace _ commandPlace+2; }; PF.ESpaceX, PF.ESpaceY => { IF spacingProc # NIL THEN { ReadBlock[handle, commandPlace+1, [LP[@integerBuffer], 0, 2]]; spacingProc[ SELECT opcode FROM PF.ESpaceX => setSpaceX, PF.ESpaceY => setSpaceY, ENDCASE => ERROR PressReaderError[UnexpectedOpCode], integerBuffer]; }; commandPlace _ commandPlace+3; }; PF.EResetSpace => { IF spacingProc # NIL THEN spacingProc[resetSpace, 0]; commandPlace _ commandPlace+1; }; PF.ESpace => { IF spaceProc # NIL THEN spaceProc[]; commandPlace _ commandPlace+1; }; PF.ESetBright, PF.ESetHue, PF.ESetSat => { IF colorProc # NIL THEN colorProc[ SELECT opcode FROM PF.ESetBright => setBrightness, PF.ESetHue => setHue, PF.ESetSat => setSaturation, ENDCASE => ERROR PressReaderError[UnexpectedOpCode], byteArg]; commandPlace _ commandPlace+2; }; PF.EShowObject => { ReadBlock[handle, commandPlace+1, [LP[@integerBuffer], 0, 2]]; IF showObjectProc # NIL THEN { handle.atObject _ TRUE; handle.dataLength _ integerBuffer; handle.dataPlace _ dataPlace; showObjectProc[handle, integerBuffer]; }; handle.atObject _ FALSE; dataPlace _ dataPlace+integerBuffer*2; commandPlace _ commandPlace+3; }; PF.EShowDots, PF.EShowDotsOpaque => { ReadBlock[handle, commandPlace+1, [LP[@dotsLength], 0, 4]]; dataLength _ PF.DoubleToLC[dotsLength]; IF showDotsProc # NIL THEN { handle.atDots _ TRUE; handle.dataPlace _ dataPlace; handle.dataLength _ dataLength; showDotsProc[ handle, SELECT opcode FROM PF.EShowDots => showDots, PF.EShowDotsOpaque => showDotsOpaque, ENDCASE => ERROR PressReaderError[UnexpectedOpCode], dataLength]; }; dataPlace _ dataPlace+2*dataLength; commandPlace _ commandPlace+5; handle.atDots _ FALSE; }; PF.EShowRectangle => { IF showRectangleProc # NIL THEN { ReadBlock[handle, commandPlace+1, [LP[@rectangleBuffer], 0, 4]]; showRectangleProc[rectangleBuffer.width, rectangleBuffer.height]; }; commandPlace _ commandPlace+5; }; ENDCASE => { IF badProc # NIL THEN badProc[opcode, commandPlace, dataPlace]; EXIT; }; END; ENDLOOP; -- opcode }; -- GetCommands GetObject: PUBLIC PROC [handle: Handle, moveToProc: MoveToProc, drawToProc: DrawToProc, drawCurveProc: DrawCurveProc] = TRUSTED { dataLength: INT _ handle.dataLength; dataPlace: INT _ handle.dataPlace; objectBuffer: MACHINE DEPENDENT RECORD [command: CARDINAL, arg1, arg2: INTEGER]; curveBuffer: MACHINE DEPENDENT RECORD [cX, cY, bX, bY, aX, aY: BcplReal]; IF NOT handle.atObject THEN ERROR PressReaderError[NotAtObject]; WHILE dataLength > 0 DO ReadBlock[handle, dataPlace, [LP[@objectBuffer], 0, 6]]; SELECT objectBuffer.command FROM PF.DMoveTo => { IF moveToProc # NIL THEN moveToProc[objectBuffer.arg1, objectBuffer.arg2]; dataPlace _ dataPlace+6; dataLength _ dataLength-3; }; PF.DDrawTo => { IF drawToProc # NIL THEN drawToProc[objectBuffer.arg1, objectBuffer.arg2]; dataPlace _ dataPlace+6; dataLength _ dataLength-3; }; PF.DDrawCurve => { IF drawCurveProc # NIL THEN { ReadBlock[handle, dataPlace+2, [LP[@curveBuffer], 0, 24]]; drawCurveProc[ BcplToMesaReal[curveBuffer.cX], BcplToMesaReal[curveBuffer.cY], BcplToMesaReal[curveBuffer.bX], BcplToMesaReal[curveBuffer.bY], BcplToMesaReal[curveBuffer.aX], BcplToMesaReal[curveBuffer.aY]]; }; dataPlace _ dataPlace+26; dataLength _ dataLength-13; }; ENDCASE; ENDLOOP; }; -- GetObject GetDots: PUBLIC PROC [handle: Handle, setCoding: SetCodingProc, setMode: SetModeProc, setWindow: SetWindowProc, setSize: SetSizeProc, setSamplingProperties: SetSamplingPropertiesProc, dotsFollow: DotsFollowProc] = TRUSTED { dataLength: INT _ handle.dataLength; dataPlace: INT _ handle.dataPlace; opBuffer: MACHINE DEPENDENT RECORD [opcode: PF.BYTE, byteArg: PF.BYTE]; dotsLength: PF.Double; windowBuffer: MACHINE DEPENDENT RECORD [one, two, three, four: CARDINAL]; IF NOT handle.atDots THEN ERROR PressReaderError[NotAtDots]; WHILE dataLength > 0 DO ReadBlock[handle, dataPlace, [LP[@opBuffer], 0, 2]]; SELECT opBuffer.opcode FROM 1 => { -- PF.DDotCode IF setCoding # NIL THEN { ReadBlock[handle, dataPlace+2, [LP[@dotsLength], 0, 4]]; setCoding[opBuffer.byteArg, dotsLength.high, dotsLength.low]; }; dataPlace _ dataPlace+6; dataLength _ dataLength-3; }; 2 => { -- PF.DDotMode IF setMode # NIL THEN setMode[opBuffer.byteArg]; dataPlace _ dataPlace+2; dataLength _ dataLength-1; }; 0 => SELECT opBuffer.byteArg FROM PF.DDotWindow => { IF setWindow # NIL THEN { ReadBlock[handle, dataPlace+2, [LP[@windowBuffer], 0, 8]]; setWindow[windowBuffer.one, windowBuffer.two, windowBuffer.three, windowBuffer.four]; }; dataPlace _ dataPlace+10; dataLength _ dataLength-5; }; PF.DDotSize => { IF setSize # NIL THEN { ReadBlock[handle, dataPlace+2, [LP[@windowBuffer], 0, 4]]; setSize[windowBuffer.one, windowBuffer.two]; }; dataPlace _ dataPlace+6; dataLength _ dataLength-3; }; PF.DDotsFollow => { dataPlace _ dataPlace+2; dataLength _ dataLength-1; IF dotsFollow # NIL THEN { pageNumber: INT _ dataPlace/512; byteOffset: INT _ dataPlace MOD 512; numberPages: INT _ (dataLength+byteOffset+255) / 256; dotsFollow[[file: handle.stream1, numberPages: numberPages, pageNumber: pageNumber, byteOffset: byteOffset, length: dataLength]]; }; dataLength _ 0; }; PF.DDotsFromFile => ERROR PressReaderError[Unimplemented]; PF.DDotsFromPressFile => ERROR PressReaderError[Unimplemented]; PF.DSampleProps => { list: LIST OF REF _ NIL; GetWord: SAFE PROC RETURNS [cardinal: CARDINAL] ~ TRUSTED { ReadBlock[handle, dataPlace, [LP[@cardinal], 0, 2]]; dataPlace _ dataPlace+2; dataLength _ dataLength-1; }; dummy: CARDINAL _ GetWord[]; dataWordsOfProperties: NAT _ GetWord[]; WHILE dataWordsOfProperties > 0 DO pointer: LONG POINTER _ NIL; words: CARDINAL _ 0; cmdWord: CARDINAL _ GetWord[]; dataWordsOfProperties _ dataWordsOfProperties - 1; SELECT cmdWord FROM PF.SSPInputIntensity => { words _ SIZE[SSPInputIntensityRep]; list _ CONS[NEW[SSPInputIntensityRep], list]; pointer _ LOOPHOLE[list.first]; }; PF.SSPOutputIntensity => { words _ SIZE[SSPOutputIntensityRep]; list _ CONS[NEW[SSPOutputIntensityRep], list]; pointer _ LOOPHOLE[list.first]; }; PF.SSPScreen => { words _ SIZE[SSPScreenRep]; list _ CONS[NEW[SSPScreenRep], list]; pointer _ LOOPHOLE[list.first]; }; 3 => { nCells: CARDINAL _ GetWord[]; ref: SSPDot _ NEW[SSPDotRep[nCells]]; dataWordsOfProperties _ dataWordsOfProperties - 1; ref.nCells _ nCells; words _ SIZE[SSPDotRep[nCells]]; list _ CONS[ref, list]; pointer _ @ref.nLines; }; ENDCASE => ERROR PressReaderError[UnexpectedOpCode]; IF words > dataWordsOfProperties THEN ERROR PressReaderError[MalformedPressFile]; IF words > dataLength THEN ERROR PressReaderError[MalformedPressFile]; ReadBlock[handle, dataPlace, [pointer, 0, 2*words]]; dataPlace _ dataPlace+2*words; dataLength _ dataLength-words; dataWordsOfProperties _ dataWordsOfProperties - words; ENDLOOP; IF setSamplingProperties # NIL THEN setSamplingProperties[list]; }; ENDCASE => ERROR PressReaderError[UnexpectedOpCode]; ENDCASE => ERROR PressReaderError[UnexpectedOpCode]; ENDLOOP; }; -- GetDots ClosePressFile: PUBLIC PROC [handle: Handle] = { IF handle#NIL THEN { IF (handle.stream1 # NIL) THEN handle.stream1.Close[]; IF (handle.stream2 # NIL) THEN handle.stream2.Close[]; handle.file.Close[]; }; handle _ NIL; }; -- ClosePressFile DecodeFace: PROC [face: INT] RETURNS [fontFace: FontFace] = { fontFace.encoding _ face; IF face IN [0..18) THEN { fontFace.texDesignSize _ 0; fontFace.slope _ IF (face MOD 2) = 0 THEN regular ELSE italic; face _ face - (face MOD 2); fontFace.weight _ SELECT (face MOD 6) FROM 0 => medium, 2 => bold, 4 => light, ENDCASE => ERROR; fontFace.expansion _ SELECT face - (face MOD 6) FROM 0 => regular, 6 => condensed, 12 => expanded, ENDCASE => ERROR; } ELSE { fontFace.texDesignSize _ (254-face)*0.5; fontFace.slope _ none; fontFace.weight _ none; fontFace.expansion _ none; }; }; -- DecodeFace Block: TYPE = RECORD[base: LONG POINTER, startIndex: INT, stopIndexPlusOne: INT]; ReadBlock: PROC [handle: Handle, index: INT, block: Block] = TRUSTED { ix1: INT _ handle.stream1.GetIndex[]; ub: IO.UnsafeBlock _ [base: LOOPHOLE[block.base], startIndex: block.startIndex, count: block.stopIndexPlusOne-block.startIndex]; IF ABS[ix1-index] > indexDistanceThreshold THEN { s: IO.STREAM _ handle.stream1; handle.stream1 _ handle.stream2; handle.stream2 _ s; }; handle.stream1.SetIndex[index]; IF handle.stream1.UnsafeGetBlock[ub] # ub.count THEN ERROR PressReaderError[AbortedBecauseGetFailed]; }; ArrayCardinalToBcplString: UNSAFE PROC [s: LONG POINTER TO ARRAY [0..0) OF CARDINAL] RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; }; ArrayByteToBcplString: UNSAFE PROC [s: LONG POINTER TO PACKED ARRAY [0..0) OF PF.BYTE] RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; }; ArrayCharacterToBcplString: UNSAFE PROC [s: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER] RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; }; BcplStringToRope: PROC [t: BcplString] RETURNS [ROPE] = TRUSTED { lengthByte: PF.BYTE _ LOOPHOLE[t[0]]; len: INT _ lengthByte; i: INT _ 0; fromProc: SAFE PROC RETURNS[CHAR] = TRUSTED { RETURN[t.body[i _ i+1]] }; IF len NOT IN[0..bcplMaxLength] THEN ERROR; RETURN [Rope.FromProc[len, fromProc]]; }; BcplToMesaReal: PROC [b: BcplReal] RETURNS [REAL] = INLINE { RETURN[RealConvert.BcplToIeee[LOOPHOLE[b]]]; }; LP: UNSAFE PROC [pointer: POINTER] RETURNS [LONG POINTER TO Basics.RawBytes] = UNCHECKED { lp: LONG POINTER _ pointer; RETURN[lp] }; END. όPressReaderImpl.mesa Copyright (C) 1982, Xerox Corporation. All rights reserved. Last Modified by Shore; November 22, 1982 11:51 am Last Edited by: Beach, September 13, 1983 5:21 pm Last Edited by: Wyatt, December 1, 1983 5:29 pm Last Edited by: Plass, March 14, 1985 8:17:34 am PST a graphically defined font Change Log Created by Shore; June 29, 1982 2:56 pm Changed by Shore; August 22, 1982 4:58 pm converted to formatted Tioga file revisions for Cedar 3.3 reduced number of SetIndex instructions Changed by Shore; August 26, 1982 9:30 am made Dots and Objects one level deeper to permit exit actions by the show Commands Changed by Shore; September 2, 1982 9:08 am made Parts individually gettable (partNumber parameter to GetParts) Changed by Shore; September 3, 1982 5:08 pm now pass up Dots Changed by Shore; October 12, 1982 9:11 pm updated for Cedar 3.4 Changed by Shore; November 14, 1982 3:02 pm changed to Cedar.Style and added node formats Changed by Plass; July 16, 1984 2:59:59 pm PDT changed to Cedar.Style and added node formats Plass, March 14, 1985 8:14:18 am PST Changed GetCommands, GetObject, and GetDots to take the callback procedures directly as parameters, rather than records of procedures (which the compiler thinks are not safe). Κ“– "Cedar" style˜codešΟc™K™šœ˜Kšœ˜Kšœ˜Kšœ žœ"˜/Kšœ žœ#˜1Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœ-˜-Kšžœ˜—Kšœ ˜K˜—šŸ œžœžœ„žœ˜₯Kšœžœ˜Kš œžœžœ žœž œ˜1Kšœžœ˜Kšœžœ˜Kš œžœž œžœžœ˜CKš œžœž œžœ žœžœ ˜]Kšœ žœž œžœ žœžœ žœžœ˜GKšœ%žœ˜)Kšœ žœ˜Kšœ žœ˜Kšžœ žœžœžœ˜7Kšžœžœžœžœ˜BKšœF˜FKšœD˜DKšœ5žœžœžœ˜Dšžœž˜"Kšœ!žœ˜Sšžœžœ ˜šžœž˜šžœžœžœ˜(Kšœžœ˜ šžœžœžœ˜"Kšœžœžœž œ˜>Kšœžœ˜?Kšœm˜mKšœ˜—Kšœ˜Kšœ˜Kšœ˜—šžœžœ žœ˜%Kšœžœ˜ Kšžœ žœžœ'˜=Kšœ˜Kšœ˜Kšœ˜—šžœžœ žœ˜'Kšœžœ˜ šžœžœžœ˜"Kšœžœžœž œ˜>Kšœžœ˜?Kšœo˜oKšœ˜—Kšœ! ˜-Kšœ˜Kšœ˜—šžœžœžœ˜*šžœžœž˜Kšœ$žœ˜B—Kšœ˜Kšœ˜—šžœžœžœ ˜$šžœžœž˜Kšœ$žœ˜B—Kšœ˜Kšœ˜—šžœžœžœ˜ šžœ žœžœ˜Kšœžœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜—š žœžœžœ žœ˜OKšžœ žœžœ ˜"Kšœ˜Kšœ˜—šžœ˜šžœ žœž˜Kšœ-˜-—Kšœ&˜&Kšœ˜—šžœ˜šžœžœžœ˜Kšœ#žœ˜CKšœ+žœ(žœ(˜Kšœ˜—Kšœ˜Kšœ˜—šžœ˜Kšžœ žœžœ˜)Kšœ˜Kšœ˜—šžœžœ ˜šžœžœžœ˜Kšœ#žœ˜>šœ ˜ šžœž˜Kšžœ˜Kšžœ˜Kšžœžœ$˜4—Kšœ˜—Kšœ˜—Kšœ˜Kšœ˜—šžœ ˜ Kšœ˜šžœžœžœ˜"Kšœžœ ž œ˜/Kšœžœ˜?Kšœh˜hKšœ˜—Kšœ˜Kšœ˜Kšœ˜—šžœ ˜ šžœ žœž˜Kšœ"˜"—Kšœ˜Kšœ˜Kšœ˜—šžœ˜4Kšœ#žœ˜>šžœ žœž˜Kšœ*˜*—Kšœ%˜%Kšœ˜Kšœ˜—šžœ˜šžœžœžœ˜"Kšœžœž œ˜)Kšœžœ ž œ˜/Kšœk˜kKšœ˜—Kšœ˜Kšœ˜—šžœ žœ ˜šžœžœžœ˜Kšœ#žœ˜>šœ ˜ šžœž˜Kšžœ˜Kšžœ˜Kšžœžœ$˜4—Kšœ˜—Kšœ˜—Kšœ˜Kšœ˜—šžœ˜Kšžœžœžœ˜5Kšœ˜Kšœ˜—šžœ ˜Kšžœ žœžœ ˜$Kšœ˜Kšœ˜—šžœ žœ žœ ˜*šžœ žœž˜šœ ˜ šžœž˜Kšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ$˜4—Kšœ ˜ ——Kšœ˜Kšœ˜—šžœ˜Kšœ#žœ˜>šžœžœžœ˜Kšœžœ˜Kšœ"˜"K˜Kšœ&˜&K˜—Kšœžœ˜Kšœ&˜&Kšœ˜K˜—šžœ žœ˜%Kšœ#žœ˜;Kšœ žœ˜'šžœžœžœ˜Kšœžœ˜Kšœ˜Kšœ˜šœ ˜ Kšœ˜šžœž˜Kšžœ˜Kšžœ#˜%Kšžœžœ$˜4—Kšœ ˜ —K˜—Kšœ#˜#Kšœ˜Kšœžœ˜K˜—šžœ˜šžœžœžœ˜!Kšœ#žœ˜@KšœA˜AKšœ˜—Kšœ˜Kšœ˜—šžœ˜ Kšžœ žœžœ*˜?Kšžœ˜Kšœ˜——Kšžœ˜—Kšžœ ˜—Kšœ˜K˜—šŸ œžœžœbžœ˜Kšœ žœ˜$Kšœ žœ˜"Kš œžœž œžœ žœžœ˜PKšœ žœž œžœ$˜IKšžœžœžœžœ˜@šžœž˜Kšœžœ˜8šžœž˜ šžœ ˜šžœžœž˜Kšœ1˜1—Kšœ˜Kšœ˜Kšœ˜—šžœ ˜šžœžœž˜Kšœ2˜2—Kšœ˜Kšœ˜Kšœ˜—šžœ˜šžœžœžœ˜Kšœ žœ˜:šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜—Kšžœ˜—Kšœ ˜K˜—šŸœžœžœ+žœžœžœžœ1žœžœ˜ίKšœ žœ˜$Kšœ žœ˜"Kšœ žœž œžœ žœžœ žœžœ˜GKšœ žœ˜Kš œžœž œžœžœ˜IKšžœžœžœžœ˜<šžœž˜Kšœžœ˜4šžœž˜šœ˜šžœ žœžœ˜Kšœ žœ˜8Kšœ=˜=Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—šœ˜šžœ žœž˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—šœžœž˜!šžœ˜šžœ žœžœ˜Kšœ žœ˜:KšœU˜UKšœ˜—Kšœ˜Kšœ˜Kšœ˜—šžœ˜šžœ žœžœ˜Kšœ žœ˜:Kšœ,˜,Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—šžœ˜Kšœ˜K˜šžœžœžœ˜Kšœ žœ˜ Kšœ žœ žœ˜$Kšœ žœ%˜5Kšœ˜K˜—Kšœ˜Kšœ˜—Kšžœžœ!˜:Kšžœžœ!˜?šžœ˜Kš œžœžœžœžœ˜š Ÿœžœžœžœ žœžœ˜;Kšœžœ˜4Kšœ˜K˜Kšœ˜—Kšœžœ ˜Kšœžœ ˜'šžœž˜"Kšœ žœžœžœ˜Kšœžœ˜Kšœ žœ ˜Kšœ2˜2šžœ ž˜šžœ˜Kšœžœ˜#Kšœžœžœ˜-Kšœ žœ ˜Kšœ˜—šžœ˜Kšœžœ˜$Kšœžœžœ˜.Kšœ žœ ˜Kšœ˜—šžœ˜Kšœžœ˜Kšœžœžœ˜%Kšœ žœ ˜Kšœ˜—˜Kšœžœ ˜Kšœžœ˜%Kšœ2˜2Kšœ˜Kšœžœ˜ Kšœžœ ˜Kšœ˜K˜—Kšžœžœ$˜4—Kšžœžœžœ&˜QKšžœžœžœ&˜FKšœ4˜4Kšœ˜Kšœ˜Kšœ6˜6Kšžœ˜—Kšžœžœžœ˜@Kšœ˜—Kšžœžœ$˜4—Kšžœžœ$˜4—Kšžœ˜—Kšœ ˜K˜—šŸœžœžœ˜0šžœžœžœ˜Kšžœžœžœ˜6Kšžœžœžœ˜6K˜K˜—Kšœ žœ˜ Kšœ˜K˜—šŸ œžœžœžœ˜=Kšœ˜šžœžœ žœ˜Kšœ˜Kš œžœžœžœ žœ˜>Kšœžœ˜šœžœžœž˜*Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšžœžœ˜—šœžœžœž˜4Kšœ ˜ Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ˜—šžœ˜Kšœ(˜(Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ ˜K˜—Kš œžœžœžœžœžœžœ˜QšŸ œžœžœžœ˜FKšœžœ˜%šœžœžœ+˜OKšœ0˜0—šžœžœ%žœ˜1KšœžœžœG˜SKšœ˜—Kšœ˜K˜šžœ.ž˜4Kšžœ+˜0—Kšœ˜K˜—šŸœžœžœžœžœžœžœžœžœžœžœžœžœ˜˜K˜—šŸœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜šK˜—šŸœžœžœžœžœžœžœžœžœž œžœžœžœžœ˜‘K˜—š Ÿœžœžœžœžœ˜AKšœ žœžœžœ˜%Kšœžœ˜Kšœžœ˜ Kš œ žœžœžœžœžœžœ˜HKš žœžœžœžœžœ˜+Kšžœ ˜&Kšœ˜K˜—š Ÿœžœžœžœžœ˜