PressReaderImpl.mesa
Last Modified by Shore; November 22, 1982 11:51 am
DIRECTORY
Environment USING [bytesPerPage, wordsPerPage],
FileIO USING [Open, OpenFailed],
IO USING [STREAM, Close, GetLength, UnsafeBlock, SetIndex, UnsafeGetBlock],
PressFormat,
PressReader,
RealConvert USING [BcplToIeee],
Rope USING [ROPE, FromProc];
PressReaderImpl: PROGRAM
IMPORTS FileIO, IO, PF: PressFormat, RealConvert, Rope
EXPORTS PressReader = BEGIN
OPEN PressReader;
ROPE: TYPE = Rope.ROPE;
bytesPerPressRecord: CARDINAL = 512;
Handle: PUBLIC TYPE = REF PressReaderRec;
PressReaderRec: PUBLIC TYPE = RECORD [
stream: 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, dataLength: INT,
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];
OpenPressFile: PUBLIC PROCEDURE [name: ROPE] RETURNS [handle: Handle] = {
docDirV: PF.DDV;
lengthInBytes: INT;
handle ← NEW[PressReaderRec];
handle.stream ← FileIO.Open[fileName: name, accessOptions: read
! FileIO.OpenFailed => CHECKED {ERROR PressReaderError[FileNotAvailableForRead]} ];
lengthInBytes ← handle.stream.GetLength[];
IF lengthInBytes = 0 OR (lengthInBytes MOD bytesPerPressRecord # 0) THEN
ERROR PressReaderError[FileNotAPressFile]; --bad length
ReadBlock[handle, lengthInBytes-bytesPerPressRecord, [@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;
}; -- OpenPressFile
GetDocumentDirectory: PUBLIC PROCEDURE [handle: Handle] RETURNS [DocumentDirectory] = {
docDirV: PF.DDV;
IF handle = NIL THEN ERROR PressReaderError[BadHandle];
ReadBlock[handle, (handle.nRecs-1)*bytesPerPressRecord, [@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 PROCEDURE [handle: Handle, partNumber: INT, pageProc: PageProc ← NIL, fontDirectoryProc: FontDirectoryProc ← NIL] = {
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,
[@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 PROCEDURE [handle: Handle, fontEntryProc: FontEntryProc ← NIL] = {
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,
[@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, [@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, medium, regular, regular],
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 PROCEDURE [handle:Handle, entityProc: EntityProc ← NIL] = {
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, [@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, [@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 PROCEDURE [handle:Handle, commandProcs: CommandProcs] = {
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, [@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 commandProcs.showCharactersProc # NIL THEN {
stringBuffer[0] ← LOOPHOLE[opcode-PF.EShowShort+1, CHARACTER];
ReadBlock[handle, dataPlace, [@stringBuffer, 1, length+1]];
commandProcs.showCharactersProc[showCharactersShort, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]];
};
dataPlace ← dataPlace+length;
commandPlace ← commandPlace+1;
};
IN [PF.ESkipShort..PF.EShowSkip) => {
length ← opcode-PF.ESkipShort+1;
IF commandProcs.skipProc # NIL THEN
commandProcs.skipProc[skipCharactersShort, length];
dataPlace ← dataPlace+length;
commandPlace ← commandPlace+1;
};
IN [PF.EShowSkip..PF.ESpaceXShort) => {
length ← opcode-PF.EShowShort+1;
IF commandProcs.showCharactersProc # NIL THEN {
stringBuffer[0] ← LOOPHOLE[opcode-PF.EShowShort+1, CHARACTER];
ReadBlock[handle, dataPlace, [@stringBuffer, 1, length+1]];
commandProcs.showCharactersProc[showCharactersAndSkip, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]];
};
dataPlace ← dataPlace+length+1; -- skip byte
commandPlace ← commandPlace+1;
};
IN [PF.ESpaceXShort..PF.ESpaceYShort) => {
IF commandProcs.spacingProc # NIL THEN
commandProcs.spacingProc[setSpaceXShort, (opcode-PF.ESpaceXShort)*256+byteArg];
commandPlace ← commandPlace+2;
};
IN [PF.ESpaceYShort..PF.EFont) => {
IF commandProcs.spacingProc # NIL THEN
commandProcs.spacingProc[setSpaceYShort, (opcode-PF.ESpaceXShort)*256+byteArg];
commandPlace ← commandPlace+2;
};
IN [PF.EFont..PF.EShortMax] => {
IF commandProcs.fontProc # NIL THEN {
value ← opcode-PF.EFont;
commandProcs.fontProc[value];
};
commandPlace ← commandPlace+1;
};
PF.ENop, IN (PF.EShortMax..PF.ESkipControlImmediate) => { --available and spare
IF commandProcs.noOpProc # NIL THEN
commandProcs.noOpProc;
commandPlace ← commandPlace+1;
};
PF.ESkipControlImmediate => {
IF commandProcs.skipProc # NIL THEN
commandProcs.skipProc[skipControlBytesImmediate, byteArg];
commandPlace ← commandPlace+2+byteArg;
};
PF.EAlternative => {
IF commandProcs.alternativeProc # NIL THEN {
ReadBlock[handle, commandPlace+1, [@alternativeBuffer, 0, 10]];
commandProcs.alternativeProc[alternativeBuffer.ELtypes, PF.DoubleToLC[alternativeBuffer.ELbytes], PF.DoubleToLC[alternativeBuffer.DLbytes]];
};
commandPlace ← commandPlace+11;
};
PF.EOnlyOnCopy => {
IF commandProcs.copyProc # NIL THEN commandProcs.copyProc[byteArg];
commandPlace ← commandPlace+2;
};
PF.ESetX, PF.ESetY => {
IF commandProcs.positionProc # NIL THEN {
ReadBlock[handle, commandPlace+1, [@integerBuffer, 0, 2]];
commandProcs.positionProc[
SELECT opcode FROM
PF.ESetX => setX,
PF.ESetY => setY,
ENDCASE => ERROR,
integerBuffer];
};
commandPlace ← commandPlace+3;
};
PF.EShow => {
length ← byteArg;
IF commandProcs.showCharactersProc # NIL THEN {
stringBuffer[0] ← LOOPHOLE[byteArg, CHARACTER];
ReadBlock[handle, dataPlace, [@stringBuffer, 1, length+1]];
commandProcs.showCharactersProc[showCharacters, length, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]];
};
dataPlace ← dataPlace+length;
commandPlace ← commandPlace+2;
};
PF.ESkip => {
IF commandProcs.skipProc # NIL THEN
commandProcs.skipProc[skipCharacters, byteArg];
dataPlace ← dataPlace+byteArg;
commandPlace ← commandPlace+2;
};
PF.ESkipControl => { -- should get the type byte too
ReadBlock[handle, commandPlace+1, [@integerBuffer, 0, 2]];
IF commandProcs.skipProc # NIL THEN
commandProcs.skipProc[skipControlBytes, integerBuffer];
dataPlace ← dataPlace+integerBuffer;
commandPlace ← commandPlace+4;
};
PF.EShowImmediate => {
IF commandProcs.showCharactersProc # NIL THEN {
stringBuffer[0] ← LOOPHOLE[1, CHARACTER];
stringBuffer[1] ← LOOPHOLE[byteArg, CHARACTER];
commandProcs.showCharactersProc[showCharacterImmediate, 1, BcplStringToRope[ArrayCharacterToBcplString[@stringBuffer]]];
};
commandPlace ← commandPlace+2;
};
PF.ESpaceX, PF.ESpaceY => {
IF commandProcs.spacingProc # NIL THEN {
ReadBlock[handle, commandPlace+1, [@integerBuffer, 0, 2]];
commandProcs.spacingProc[
SELECT opcode FROM
PF.ESpaceX => setSpaceX,
PF.ESpaceY => setSpaceY,
ENDCASE => ERROR,
integerBuffer];
};
commandPlace ← commandPlace+3;
};
PF.EResetSpace => {
IF commandProcs.spacingProc # NIL THEN
commandProcs.spacingProc[resetSpace, 0];
commandPlace ← commandPlace+1;
};
PF.ESpace => {
IF commandProcs.spaceProc # NIL THEN commandProcs.spaceProc;
commandPlace ← commandPlace+1;
};
PF.ESetBright, PF.ESetHue, PF.ESetSat => {
IF commandProcs.colorProc # NIL THEN
commandProcs.colorProc[
SELECT opcode FROM
PF.ESetBright => setBrightness,
PF.ESetHue => setHue,
PF.ESetSat => setSaturation,
ENDCASE => ERROR,
byteArg];
commandPlace ← commandPlace+2;
};
PF.EShowObject => {
ReadBlock[handle, commandPlace+1, [@integerBuffer, 0, 2]];
IF commandProcs.showObjectProc # NIL THEN {
handle.atObject ← TRUE;
handle.dataLength ← integerBuffer;
handle.dataPlace ← dataPlace;
commandProcs.showObjectProc[handle, integerBuffer];
};
handle.atObject ← FALSE;
dataPlace ← dataPlace+integerBuffer*2;
commandPlace ← commandPlace+3;
};
PF.EShowDots, PF.EShowDotsOpaque => {
ReadBlock[handle, commandPlace+1, [@dotsLength, 0, 4]];
dataLength ← PF.DoubleToLC[dotsLength];
IF commandProcs.showDotsProc # NIL THEN {
handle.atDots ← TRUE;
handle.dataPlace ← dataPlace;
handle.dataLength ← dataLength;
commandProcs.showDotsProc[
handle,
SELECT opcode FROM
PF.EShowDots => showDots,
PF.EShowDotsOpaque => showDotsOpaque,
ENDCASE => ERROR,
dataLength];
};
dataPlace ← dataPlace+2*dataLength;
commandPlace ← commandPlace+5;
handle.atDots ← FALSE;
};
PF.EShowRectangle => {
IF commandProcs.showRectangleProc # NIL THEN {
ReadBlock[handle, commandPlace+1, [@rectangleBuffer, 0, 4]];
commandProcs.showRectangleProc[rectangleBuffer.width, rectangleBuffer.height];
};
commandPlace ← commandPlace+5;
};
ENDCASE => {
IF commandProcs.badProc # NIL THEN
commandProcs.badProc[opcode, commandPlace, dataPlace];
EXIT;
};
END;
ENDLOOP; -- opcode
}; -- GetCommands
GetObject: PUBLIC PROCEDURE [handle: Handle, objectProcs: ObjectProcs] = {
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, [@objectBuffer, 0, 6]];
SELECT objectBuffer.command FROM
PF.DMoveTo => {
IF objectProcs.moveToProc # NIL THEN
objectProcs.moveToProc[objectBuffer.arg1, objectBuffer.arg2];
dataPlace ← dataPlace+6;
dataLength ← dataLength-3;
};
PF.DDrawTo => {
IF objectProcs.drawToProc # NIL THEN
objectProcs.drawToProc[objectBuffer.arg1, objectBuffer.arg2];
dataPlace ← dataPlace+6;
dataLength ← dataLength-3;
};
PF.DDrawCurve => {
IF objectProcs.drawCurveProc # NIL THEN {
ReadBlock[handle, dataPlace+2, [@curveBuffer, 0, 24]];
objectProcs.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 PROCEDURE [handle: Handle, dotProcs: DotProcs] = {
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];
numberPages, pageNumber, byteOffset: INT;
IF NOT handle.atDots THEN ERROR PressReaderError[NotAtDots];
WHILE dataLength > 0 DO
ReadBlock[handle, dataPlace, [@opBuffer, 0, 2]];
SELECT opBuffer.opcode FROM
1 => { -- PF.DDotCode
IF dotProcs.setCoding # NIL THEN {
ReadBlock[handle, dataPlace+2, [@dotsLength, 0, 4]];
dotProcs.setCoding[opBuffer.byteArg, dotsLength.high, dotsLength.low];
};
dataPlace ← dataPlace+6;
dataLength ← dataLength-3;
};
2 => { -- PF.DDotMode
IF dotProcs.setMode # NIL THEN
dotProcs.setMode[opBuffer.byteArg];
dataPlace ← dataPlace+2;
dataLength ← dataLength-1;
};
0 => SELECT opBuffer.byteArg FROM
PF.DDotWindow => {
IF dotProcs.setWindow # NIL THEN {
ReadBlock[handle, dataPlace+2, [@windowBuffer, 0, 8]];
dotProcs.setWindow[windowBuffer.one, windowBuffer.two, windowBuffer.three, windowBuffer.four];
};
dataPlace ← dataPlace+10;
dataLength ← dataLength-5;
};
PF.DDotSize => {
IF dotProcs.setSize # NIL THEN {
ReadBlock[handle, dataPlace+2, [@windowBuffer, 0, 4]];
dotProcs.setSize[windowBuffer.one, windowBuffer.two];
};
dataPlace ← dataPlace+6;
dataLength ← dataLength-3;
};
PF.DDotsFollow => {
dataPlace ← dataPlace+2;
dataLength ← dataLength-1;
IF dotProcs.dotsFollow # NIL THEN {
pageNumber ← dataPlace/Environment.bytesPerPage;
byteOffset ← dataPlace MOD Environment.bytesPerPage;
numberPages ← (dataLength+byteOffset+Environment.wordsPerPage-1) / Environment.wordsPerPage;
dotProcs.dotsFollow[[file: handle.stream, numberPages: numberPages, pageNumber: pageNumber, byteOffset: byteOffset, length: dataLength]];
};
dataLength ← 0;
};
PF.DDotsFromFile => ERROR;
PF.DDotsFromPressFile => ERROR;
PF.DSampleProps => ERROR;
ENDCASE => ERROR;
ENDCASE => ERROR;
ENDLOOP;
}; -- GetDots
ClosePressFile: PUBLIC PROCEDURE [handle: Handle] = {
IF (handle # NIL) AND (handle.stream # NIL) THEN handle.stream.Close[];
handle ← NIL;
}; -- ClosePressFile
DecodeFace: PROCEDURE [face: INT] RETURNS [fontFace: FontFace] = {
IF face NOT IN [0..18) THEN RETURN [[face, medium, regular, regular]];
fontFace.encoding ← face;
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;
}; -- DecodeFace
ReadBlock: PROCEDURE [handle: Handle, index: INT, ub: IO.UnsafeBlock] = INLINE {
handle.stream.SetIndex[index];
IF handle.stream.UnsafeGetBlock[ub] # (ub.stopIndexPlusOne-ub.startIndex) THEN
ERROR PressReaderError[AbortedBecauseGetFailed];
};
ArrayCardinalToBcplString: PROCEDURE [s: LONG POINTER TO ARRAY [0..0) OF CARDINAL]
RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; };
ArrayByteToBcplString: PROCEDURE [s: LONG POINTER TO PACKED ARRAY [0..0) OF PF.BYTE]
RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; };
ArrayCharacterToBcplString: PROCEDURE [s: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER]
RETURNS [BcplString] = INLINE { RETURN[LOOPHOLE[s, BcplString]]; };
BcplStringToRope: PROCEDURE [t: BcplString] RETURNS [ROPE] = {
lengthByte: PF.BYTELOOPHOLE[t[0]];
len: INT ← lengthByte;
i: INT ← 0;
fromProc: SAFE PROCEDURE RETURNS[CHAR] = TRUSTED { RETURN[t.body[i ← i+1]]; };
IF len NOT IN[0..bcplMaxLength] THEN ERROR;
RETURN [Rope.FromProc[len, fromProc]];
};
BcplToMesaReal: PROCEDURE [b: BcplReal] RETURNS [REAL] = INLINE {
RETURN[RealConvert.BcplToIeee[LOOPHOLE[b]]]; };
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