DIRECTORY
IODefs: FROM "iodefs",
StreamDefs: FROM "streamdefs",
StringDefs: FROM "stringdefs",
SystemDefs: FROM "systemdefs",
PressDefs: FROM "pressdefs";

Matrix: PROGRAM IMPORTS IODefs, StreamDefs, StringDefs, SystemDefs, PressDefs =
BEGIN

Font:TYPE = POINTER TO FontBody;
FontBody:TYPE = RECORD[family:STRING, size:CARDINAL ← 0, face:CARDINAL ← 0,
rotation:CARDINAL ← 0, widths:Widths ← NIL];
Widths:TYPE = POINTER TO WidthBody;
WidthBody:TYPE = RECORD[micaX:ARRAY [0..256) OF INTEGER,
bBox:ARRAY [0..4) OF INTEGER];
JustificationMode: TYPE = {leftJustified, rightJustified, centered,
bottomJustified, topJustified};

labelFont, entryFont, titleFont, commentFont, quoteFont, screamerFont1, screamerFont2: Font ← NIL;
wStream:StreamDefs.StreamHandle; --Fonts.Widths stream
outFile:POINTER TO PressDefs.PressFileDescriptor;
outFileName:STRING = "Title.Press";
str:STRING ← [40];
row,column:CARDINAL;
char:CHARACTER;

leftEdge:CARDINAL←4000;
rightEdge:CARDINAL←19000;
bottomEdge:CARDINAL←3000;
topEdge:CARDINAL←15000;
gridWidth:CARDINAL←20;
labelMargin:CARDINAL←200;
titleMargin:CARDINAL←400;
title:STRING = "The common names of the seven bit character codes.";

numCols:CARDINAL=8;
numRows:CARDINAL=16;
colWidth:CARDINAL=(rightEdge-leftEdge)/numCols;
rowHeight:CARDINAL=(topEdge-bottomEdge)/numRows;

PutBox:
PROCEDURE[thick,wide,high,x,y:CARDINAL]=
BEGIN
PressDefs.PutRectangle[outFile,x-wide/2-thick/2,y-high/2-thick/2,wide+thick,thick];
PressDefs.PutRectangle[outFile,x-wide/2-thick/2,y-high/2-thick/2,thick,high+thick];
PressDefs.PutRectangle[outFile,x-wide/2-thick/2,y+high/2-thick/2,wide+thick,thick];
PressDefs.PutRectangle[outFile,x+wide/2-thick/2,y-high/2-thick/2,thick,high+thick];
END;

FindWidths:
PROCEDURE[f:Font]=
BEGIN
success:BOOLEAN;
IF f=NIL THEN ERROR AttemptToFindWidthsOfNIL;
f.widths ← SystemDefs.AllocateHeapNode[SIZE[WidthBody]];
success ← PressDefs.LookupFontName[wStream, f.family, f.face, f.size,
f.rotation, @f.widths.micaX, NIL, @f.widths.bBox];
IF ~success THEN ERROR FontNotInWidthDictionary;
END;
FontNotInWidthDictionary: SIGNAL = CODE;
AttemptToFindWidthsOfNIL: SIGNAL = CODE;

PutString:
PROCEDURE[s:STRING,f:Font,x,y:CARDINAL,m:JustificationMode]=
BEGIN
length:CARDINAL ← 0;
height, i:CARDINAL;
IF f.widths=NIL THEN ERROR FontHasNoWidthData;
FOR i IN [0..s.length) DO
length ← length+f.widths.micaX[s[i]-0C];
ENDLOOP;
height ← f.widths.bBox[3]*8/10;
SELECT m FROM
leftJustified => BEGIN y ← y-height/2 END;
rightJustified => BEGIN y ← y-height/2; x ← x-length END;
centered => BEGIN y ← y-height/2; x ← x-length/2 END;
topJustified => BEGIN y ← y-height; x ← x-length/2 END;
bottomJustified => BEGIN x ← x-length/2 END;
ENDCASE;
PressDefs.SetFont[outFile, f.family, f.size, f.face, f.rotation];
PressDefs.PutText[outFile, s, x, y];
END;
FontHasNoWidthData:SIGNAL = CODE;

InitFont: PROCEDURE[fam:STRING, size:CARDINAL, face,rot:CARDINAL ← 0]
RETURNS [Font] =
BEGIN
f:Font;
f ← SystemDefs.AllocateHeapNode[SIZE[FontBody]];
f↑ ← FontBody[fam,size,face,rot,NIL];
RETURN [f];
END;

PutChar: PROCEDURE[char:CHARACTER, font:Font,x,y:CARDINAL] = INLINE
BEGIN
string:STRING ← [1];
string.length ← 1;
string[0] ← char;
PutString[string,font,x,y,centered];
END;

PutStringChar: PROCEDURE[string1:STRING,font1:Font,char:CHARACTER,
font2:Font,x,y:CARDINAL] = INLINE
BEGIN
string2:STRING ← [1];
string2.length ← 1;
string2[0] ← char;
PutStringString[string1,font1,string2,font2,x,y];
END;

PutStringString: PROCEDURE[string1:STRING,font1:Font,string2:STRING,
font2:Font,x,y:CARDINAL] = INLINE
BEGIN
PutString[string1,font1,x,y+50,bottomJustified];
PutString[string2,font2,x,y,topJustified];
END;

IODefs.WriteLine["Starting:"];
wStream ← StreamDefs.NewWordStream["Fonts.Widths",
StreamDefs.Read];
outFile ← SystemDefs.AllocateHeapNode[SIZE[PressDefs.PressFileDescriptor]];
PressDefs.InitPressFileDescriptor[outFile,outFileName];
labelFont ← InitFont["TimesRoman",10];
entryFont ← InitFont["TimesRoman",12];
titleFont ← InitFont["TimesRoman",12];
commentFont ← InitFont["TimesRoman",10];
quoteFont ← InitFont["Gacha",12];
screamerFont1 ← InitFont["OldEnglish",48];
screamerFont2 ← InitFont["OldEnglish",36];

FindWidths[labelFont];
FindWidths[entryFont];
FindWidths[titleFont];
FindWidths[commentFont];
FindWidths[quoteFont];
FindWidths[screamerFont1];
FindWidths[screamerFont2];

--Put down the rules of the grid;
FOR row IN [0..numRows]
DO
PressDefs.PutRectangle[outFile,leftEdge,bottomEdge+row*rowHeight,
numCols*colWidth+gridWidth,gridWidth]
ENDLOOP;
FOR column IN [0..numCols]
DO
PressDefs.PutRectangle[outFile,leftEdge+column*colWidth,bottomEdge,
gridWidth,numRows*rowHeight+gridWidth]
ENDLOOP;

--Put numeric labels on the grid, in labelFont;
FOR column IN [0..numCols)
DO
str[0]←(’0)+column;
str.length ← 1;
PutString[str, labelFont, leftEdge+colWidth/2+column*colWidth,
bottomEdge+labelMargin+numRows*rowHeight,bottomJustified];
ENDLOOP;
FOR row IN [0..numRows)
DO
str.length←0;
StringDefs.AppendChar[str,’#];
SELECT row*numCols FROM
IN [0B..7B] => StringDefs.AppendString[str,"00"];
IN [10B..77B] => StringDefs.AppendString[str,"0"];
ENDCASE;
StringDefs.AppendNumber[str,row*numCols,8];
PutString[str, labelFont, leftEdge-labelMargin,
bottomEdge+(numRows-row)*rowHeight-(rowHeight/2), rightJustified];
ENDLOOP;

--put title at the bottom of the page
PutString[title, titleFont, leftEdge+(numCols*colWidth/2),
bottomEdge-titleMargin, topJustified];

--Put screaming headline on document
PutString["GrantCharacters.Press:",screamerFont2,11300,23000,centered];
PutString["A Font Sampler",screamerFont1,11300,20400,centered];
PutBox[50,13800,6000,11300,21500];
PutBox[100,14100,6300,11300,21500];

--start putting in keys

FOR char IN [0C..177C]
DO BEGIN
l:CARDINAL;
x,y,row,column:CARDINAL;
l←char-0C;
row←l/numCols;
column ← l MOD numCols;
x ← leftEdge+column*colWidth+colWidth/2;
y ← bottomEdge+(numRows-row)*rowHeight-rowHeight/2;
SELECT char FROM
=0C => PutString["NULL",commentFont,x,y,centered];
IN [1C..37C] =>

BEGIN
str:STRING ← [2];
str.length ← 2;
str[0] ← ’↑;
str[1] ← char+100B;
PutString[str,entryFont,x,y,centered];
END;
=40C => PutString["SPACE",commentFont,x,y,centered];
=41C => PutChar[char,entryFont,x,y];
=42C => PutChar[char,quoteFont,x,y];
IN [43C..54C] => PutChar[char,entryFont,x,y];
=55C => PutChar[30C,entryFont,x,y];
IN [56C..176C] => PutChar[char,entryFont,x,y];
=177C => PutString["DEL",commentFont,x,y,centered];
ENDCASE;
END
ENDLOOP;

PressDefs.WritePage[outFile];

PressDefs.ClosePressFile[outFile];

IODefs.WriteLine[""];
IODefs.WriteLine["Done."]

END.