-- TexIO.mesa
-- last written by Doug Wyatt, January 3, 1980 1:56 PM
DIRECTORY
TexDefs: FROM "TexDefs",
TexMathDefs: FROM "TexMathDefs",
TexIODefs: FROM "TexIODefs",
TexStringDefs: FROM "TexStringDefs"
USING[AppendChar,AppendNumber],
DisplayDefs: FROM "DisplayDefs"
USING[SetFont],
FontDefs: FROM "FontDefs"
USING[FontHandle,CreateFont],
ImageDefs: FROM "ImageDefs"
USING[CleanupItem,CleanupMask,CleanupProcedure,AddCleanupProcedure],
InlineDefs: FROM "InlineDefs"
USING[LongMult,LongDiv,DIVMOD],
SegmentDefs: FROM "SegmentDefs",
StreamDefs: FROM "StreamDefs"
USING[GetDefaultKey,GetDefaultDisplayStream];
TexIO: PROGRAM
IMPORTS TexStringDefs,
DisplayDefs,FontDefs,ImageDefs,InlineDefs,SegmentDefs,StreamDefs
EXPORTS TexIODefs =
BEGIN OPEN TexMathDefs,TexDefs,TexIODefs;
in: StreamHandle; -- the current input stream
out: StreamHandle; -- the current output stream
disp: StreamHandle; -- the default display stream
loc,dloc: CARDINAL;
GetStream: PUBLIC PROCEDURE RETURNS[StreamHandle] =
BEGIN RETURN[out] END;
SetStream: PUBLIC PROCEDURE[stream: StreamHandle] =
BEGIN
IF out=disp THEN dloc←loc;
out←stream; loc←0;
END;
UseDisplay: PUBLIC PROCEDURE =
BEGIN out←disp; loc←dloc END;
Wc: PUBLIC PROCEDURE[c: CHARACTER] = -- write a character
BEGIN
out.put[out,c];
IF c=CR THEN loc←0 ELSE loc←loc+1;
END;
Cr: PUBLIC PROCEDURE = BEGIN Wc[CR] END; -- write a carriage return
Sp: PUBLIC PROCEDURE = BEGIN Wc[SP] END; -- write a space
esc: CHARACTER←'\;
SetEsc: PUBLIC PROCEDURE[c: CHARACTER] = BEGIN esc←c END; -- set esc
Esc: PUBLIC PROCEDURE = BEGIN Wc[esc] END; -- write the escape char
Loc: PUBLIC PROCEDURE RETURNS[CARDINAL] = -- return the current location
BEGIN RETURN[loc] END;
Tab: PUBLIC PROCEDURE[tloc: CARDINAL] = -- tab over to location tloc
BEGIN WHILE loc<tloc DO Sp ENDLOOP END;
Ws: PUBLIC PROCEDURE[s: STRING] = -- write a string
BEGIN
i: CARDINAL;
FOR i IN[0..s.length) DO Wc[s[i]] ENDLOOP;
END;
Wss: PUBLIC PROCEDURE[s: STRING, i1,i2: CARDINAL] = -- write a substring
BEGIN
i: CARDINAL;
FOR i IN[i1..MIN[i2,s.length]) DO Wc[s[i]] ENDLOOP;
END;
WNum: PROCEDURE[val: UNSPECIFIED, radix: CARDINAL,
signed: BOOLEAN, columns: CARDINAL] =
BEGIN OPEN TexStringDefs;
fill: CHARACTER←(IF radix=10 THEN SP ELSE '0);
s: STRING ← [7]; -- large enough if smallest radix is 8
IF signed AND INTEGER[val]<0 THEN
BEGIN AppendChar[s,'-]; val←-val END;
AppendNumber[s,val,radix];
THROUGH (s.length..columns] DO Wc[fill] ENDLOOP;
Ws[s];
RETURN
END;
Wn: PUBLIC PROCEDURE[n: INTEGER] = -- write a signed decimal number
BEGIN WNum[n,10,TRUE,0] END;
Wnf: PUBLIC PROCEDURE[n: CARDINAL, f: CARDINAL] = -- unsigned decimal, f columns
BEGIN WNum[n,10,FALSE,f] END;
Wo: PUBLIC PROCEDURE[o: CARDINAL] = -- write an unsigned octal number
BEGIN WNum[o,10B,FALSE,0] END;
WFont: PUBLIC PROCEDURE[f: Font] =
BEGIN
Esc; Wc[':]; Wc['@+f];
END;
WFChar: PUBLIC PROCEDURE[fc: FChar] =
BEGIN
WFont[fc.font]; Sp; Wc[fc.char];
END;
WCode: PROCEDURE[x: UNSPECIFIED] =
BEGIN
Wc['']; WNum[x,8,FALSE,3];
END;
mfname: ARRAY MFont OF STRING = ["rm","it","sy","ex"];
mfbias: ARRAY MFont OF CARDINAL = [0,200B,400B,600B];
WMFont: PUBLIC PROCEDURE[m: MFont] =
BEGIN
Ws[IF m IN MFont THEN mfname[m] ELSE "??"];
END;
WMChar: PUBLIC PROCEDURE[mchar: MChar] =
BEGIN
WMFont[mchar.mfont]; WCode[mchar.char];
END;
WMCharOctal: PUBLIC PROCEDURE[mchar: MChar] =
BEGIN
n: CARDINAL←LOOPHOLE[mchar.char];
mf: MFont;
IF (mf←mchar.mfont) IN MFont THEN n←n+mfbias[mf];
WCode[n];
END;
WDimn: PUBLIC PROCEDURE[d: Dimn] = -- write value of d in points
BEGIN OPEN InlineDefs;
neg: BOOLEAN←(d<0);
hpts,frac: CARDINAL;
pts: INTEGER;
hpts←LongDiv[(LongMult[ABS[d],72*100]+2540/2),2540]; -- hundreths of points
[pts,frac]←DIVMOD[pts,100];
Wn[IF neg THEN -pts ELSE pts];
Wc['.]; WNum[frac,10,FALSE,2];
END;
-- input procedures
ReadChar: PUBLIC PROCEDURE RETURNS[CHARACTER] =
BEGIN RETURN[in.get[in]] END;
ControlH: CHARACTER = 'H-100B;
ControlQ: CHARACTER = 'Q-100B;
ControlR: CHARACTER = 'R-100B;
ControlV: CHARACTER = 'V-100B;
ControlW: CHARACTER = 'W-100B;
ControlX: CHARACTER = 'X-100B;
DEL: CHARACTER = 177C;
ReadLine: PUBLIC PROCEDURE[s: STRING] =
BEGIN
c: CHARACTER;
Clear: PROCEDURE[c, oldc: CHARACTER] = --INLINE--
BEGIN
WITH out SELECT FROM
Display => BEGIN clearChar[out,oldc]; loc←loc-1 END;
ENDCASE => Wc[c];
END;
Appnd: PROCEDURE[c: CHARACTER] = --INLINE--
BEGIN
TexStringDefs.AppendChar[s,c]; Wc[c];
END;
c ← in.get[in];
s.length ← 0;
UNTIL c=CR DO SELECT c FROM
DEL,ControlH => -- clear character
IF s.length>0 THEN
BEGIN Clear[c, s[s.length-1]]; s.length ← s.length-1 END;
ControlW => -- clear word
BEGIN -- text to be backed up is of the form
-- ...<li><v><ti>; the <v> and <ti> are to be removed.
i: CARDINAL;
state: {ti, v, li} ← ti;
FOR i DECREASING IN [0..s.length)
DO
SELECT s[i] FROM
IN['A..'Z],IN['a..'z],IN['0..'9] => IF state=ti THEN state←v;
ENDCASE => IF state=v THEN state←li;
IF state = li THEN GO TO Done;
Clear[ControlH, s[i]];
REPEAT
Done => s.length ← i+1;
FINISHED => s.length ← 0;
ENDLOOP;
END;
ControlX => -- clear line
BEGIN
WITH out SELECT FROM
Display => BEGIN clearCurrentLine[out]; loc←0 END;
ENDCASE => Wc[c];
s.length ← 0;
END;
-- ControlV => Appnd[in.get[in]];
ENDCASE => Appnd[c];
c ← in.get[in];
ENDLOOP;
END;
-- initialization
font: FontDefs.FontHandle←NIL;
GetTexFont: PROCEDURE[name: STRING] =
BEGIN OPEN SegmentDefs;
fh: FileHandle;
seg: FileSegmentHandle;
fh←NewFile[name, Read, OldFileOnly !FileNameError => GOTO NotThere];
seg←NewFileSegment[fh, DefaultBase, DefaultPages, Read];
font←FontDefs.CreateFont[seg];
EXITS NotThere => RETURN;
END;
IOCleanupItem: ImageDefs.CleanupItem ← [link:,
proc: IOCleanupProc,
mask: ImageDefs.CleanupMask[Restore]];
IOCleanupProc: ImageDefs.CleanupProcedure =
BEGIN
SELECT why FROM
Restore => IF font#NIL THEN DisplayDefs.SetFont[font];
ENDCASE;
END;
IOInit: PROCEDURE =
BEGIN
in←StreamDefs.GetDefaultKey[];
out←disp←StreamDefs.GetDefaultDisplayStream[];
loc←dloc←0;
GetTexFont["TexFont.al"];
ImageDefs.AddCleanupProcedure[@IOCleanupItem];
IOCleanupProc[Restore];
END;
IOInit;
END.