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
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.STREAMNIL,
stream2: IO.STREAMNIL,
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: BOOLFALSE,
atDots: BOOLFALSE,
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 {
a graphically defined font
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 REFNIL;
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 POINTERNIL;
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.BYTELOOPHOLE[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.
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).